Add GtkBuilder, fixes #172535
authorJohan Dahlin <jdahlin@async.com.br>
Fri, 15 Jun 2007 17:53:46 +0000 (17:53 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Fri, 15 Jun 2007 17:53:46 +0000 (17:53 +0000)
2007-06-15  Johan Dahlin  <jdahlin@async.com.br>

    * demos/gtk-demo/Makefile.am:
    * demos/gtk-demo/builder.c: (quit_activate), (about_activate),
    (do_builder):
    * demos/gtk-demo/demo.ui:
    * docs/reference/gtk/gtk-docs.sgml:
    * docs/reference/gtk/gtk-sections.txt:
    * docs/reference/gtk/gtk.types:
    * docs/reference/gtk/tmpl/gtkbuildable.sgml:
    * docs/reference/gtk/tmpl/gtkbuilder.sgml:
    * gtk/Makefile.am:
    * gtk/gtk.h:
    * gtk/gtk.symbols:
    * gtk/gtkaction.c: (gtk_action_buildable_init),
    (gtk_action_buildable_set_name), (gtk_action_buildable_get_name):
    * gtk/gtkactiongroup.c: (gtk_action_group_get_type),
    (gtk_action_group_buildable_init),
    (gtk_action_group_buildable_add),
    (gtk_action_group_buildable_set_name),
    (gtk_action_group_buildable_get_name):
    * gtk/gtkbuildable.c: (gtk_buildable_get_type),
    (gtk_buildable_set_name), (gtk_buildable_get_name),
    (gtk_buildable_add), (gtk_buildable_set_property),
    (gtk_buildable_parser_finished), (gtk_buildable_construct_child),
    (gtk_buildable_custom_tag_start), (gtk_buildable_custom_tag_end),
    (gtk_buildable_custom_finished),
    (gtk_buildable_get_internal_child):
    * gtk/gtkbuildable.h:
    * gtk/gtkbuilder.c: (gtk_builder_class_init), (gtk_builder_init),
    (gtk_builder_finalize), (gtk_builder_set_property),
    (gtk_builder_get_property), (_gtk_builder_resolve_type_lazily),
    (gtk_builder_real_get_type_from_name),
    (gtk_builder_get_parameters), (gtk_builder_get_internal_child),
    (_gtk_builder_construct), (_gtk_builder_add),
    (apply_delayed_properties), (_gtk_builder_finish),
    (gtk_builder_new), (gtk_builder_add_from_file),
    (gtk_builder_add_from_string), (gtk_builder_get_object),
    (object_add_to_list), (gtk_builder_get_objects),
    (gtk_builder_set_translation_domain),
    (gtk_builder_get_translation_domain),
    (gtk_builder_connect_signals_default),
    (gtk_builder_connect_signals), (gtk_builder_connect_signals_full),
    (gtk_builder_value_from_string),
    (gtk_builder_value_from_string_type),
    (_gtk_builder_enum_from_string), (_gtk_builder_flags_from_string),
    (gtk_builder_get_type_from_name), (gtk_builder_error_quark):
    * gtk/gtkbuilder.h:
    * gtk/gtkbuilderparser.c: (state_push), (state_peek), (state_pop),
    (error_missing_attribute), (error_invalid_attribute),
    (error_invalid_tag), (builder_construct), (parse_object),
    (free_object_info), (_get_type_by_symbol), (parse_child),
    (free_child_info), (parse_property), (free_property_info),
    (parse_signal), (_free_signal_info), (parse_interface),
    (create_subparser), (free_subparser), (subparser_start),
    (subparser_end), (parse_custom), (start_element), (end_element),
    (text), (_gtk_builder_parser_parse_buffer):
    * gtk/gtkbuilderprivate.h:
    * gtk/gtkcelllayout.c: (attributes_start_element),
    (attributes_text_element),
    (_gtk_cell_layout_buildable_custom_tag_start),
    (_gtk_cell_layout_buildable_custom_tag_end),
    (_gtk_cell_layout_buildable_add):
    * gtk/gtkcelllayout.h:
    * gtk/gtkcellview.c: (gtk_cell_view_buildable_init),
    (gtk_cell_view_buildable_custom_tag_start),
    (gtk_cell_view_buildable_custom_tag_end):
    * gtk/gtkcolorseldialog.c:
    (gtk_color_selection_dialog_buildable_interface_init),
    (gtk_color_selection_dialog_buildable_get_internal_child):
    * gtk/gtkcombobox.c: (gtk_combo_box_buildable_init),
    (gtk_combo_box_buildable_custom_tag_start),
    (gtk_combo_box_buildable_custom_tag_end):
    * gtk/gtkcomboboxentry.c:
    (gtk_combo_box_entry_buildable_interface_init),
    (gtk_combo_box_entry_buildable_get_internal_child):
    * gtk/gtkcontainer.c: (gtk_container_get_type),
    (gtk_container_buildable_init), (gtk_container_buildable_add),
    (gtk_container_buildable_set_child_property),
    (attributes_start_element), (attributes_text_element),
    (gtk_container_buildable_custom_tag_start),
    (gtk_container_buildable_custom_tag_end):
    * gtk/gtkdebug.h:
    * gtk/gtkdialog.c: (gtk_dialog_buildable_interface_init),
    (gtk_dialog_buildable_get_internal_child),
    (attributes_start_element), (attributes_text_element),
    (gtk_dialog_buildable_custom_tag_start),
    (gtk_dialog_buildable_custom_finished):
    * gtk/gtkentrycompletion.c: (gtk_entry_completion_buildable_init):
    * gtk/gtkexpander.c: (gtk_expander_buildable_add),
    (gtk_expander_buildable_init):
    * gtk/gtkfontsel.c:
    (gtk_font_selection_dialog_buildable_interface_init),
    (gtk_font_selection_dialog_buildable_get_internal_child):
    * gtk/gtkframe.c: (gtk_frame_buildable_init),
    (gtk_frame_buildable_add):
    * gtk/gtkiconview.c: (gtk_icon_view_buildable_init),
    (gtk_icon_view_buildable_custom_tag_start),
    (gtk_icon_view_buildable_custom_tag_end):
    * gtk/gtkliststore.c: (gtk_list_store_buildable_init),
    (list_store_start_element), (list_store_end_element),
    (list_store_text), (gtk_list_store_buildable_custom_tag_start),
    (gtk_list_store_buildable_custom_tag_end):
    * gtk/gtkmain.c:
    * gtk/gtknotebook.c: (gtk_notebook_buildable_init),
    (gtk_notebook_buildable_add):
    * gtk/gtksizegroup.c: (gtk_size_group_buildable_init),
    (size_group_start_element),
    (gtk_size_group_buildable_custom_tag_start),
    (gtk_size_group_buildable_custom_finished):
    * gtk/gtktreestore.c: (gtk_tree_store_buildable_init),
    (tree_model_start_element),
    (gtk_tree_store_buildable_custom_tag_start),
    (gtk_tree_store_buildable_custom_finished):
    * gtk/gtktreeview.c: (gtk_tree_view_buildable_init),
    (gtk_tree_view_buildable_add):
    * gtk/gtktreeviewcolumn.c: (gtk_tree_view_column_buildable_init):
    * gtk/gtkuimanager.c: (gtk_ui_manager_buildable_init),
    (gtk_ui_manager_buildable_add),
    (gtk_ui_manager_buildable_construct_child),
    (gtk_ui_manager_buildable_custom_tag_start),
    (gtk_ui_manager_buildable_custom_tag_end):
    * gtk/gtkwidget.c: (gtk_widget_get_type),
    (gtk_widget_buildable_interface_init),
    (gtk_widget_buildable_set_name), (gtk_widget_buildable_get_name),
    (gtk_widget_buildable_set_property),
    (gtk_widget_buildable_parser_finshed), (accel_group_start_element),
    (gtk_widget_buildable_custom_tag_start),
    (gtk_widget_buildable_custom_finshed):
    * gtk/gtkwindow.c: (gtk_window_buildable_interface_init),
    (gtk_window_buildable_set_property),
    (gtk_window_buildable_parser_finished):
    * tests/Makefile.am:
    * tests/buildertest.c: (builder_new_from_string), (test_parser),
    (signal_normal), (signal_after), (signal_object),
    (signal_object_after), (signal_first), (signal_second),
    (signal_extra), (signal_extra2), (test_connect_signals),
    (test_uimanager_simple), (test_domain), (test_translation),
    (test_sizegroup), (test_list_store), (test_tree_store),
    (test_types), (test_spin_button), (test_notebook),
    (test_construct_only_property), (test_children),
    (test_child_properties), (test_treeview_column), (test_icon_view),
    (test_combo_box), (test_combo_box_entry), (test_cell_view),
    (test_dialog), (test_accelerators), (test_widget), (main):

    Add GtkBuilder, fixes #172535

svn path=/trunk/; revision=18141

46 files changed:
ChangeLog
demos/gtk-demo/Makefile.am
demos/gtk-demo/builder.c [new file with mode: 0644]
demos/gtk-demo/demo.ui [new file with mode: 0644]
docs/reference/gtk/gtk-docs.sgml
docs/reference/gtk/gtk-sections.txt
docs/reference/gtk/gtk.types
docs/reference/gtk/tmpl/gtkbuildable.sgml [new file with mode: 0644]
docs/reference/gtk/tmpl/gtkbuilder.sgml [new file with mode: 0644]
gtk/Makefile.am
gtk/gtk.h
gtk/gtk.symbols
gtk/gtkaction.c
gtk/gtkactiongroup.c
gtk/gtkbuildable.c [new file with mode: 0644]
gtk/gtkbuildable.h [new file with mode: 0644]
gtk/gtkbuilder.c [new file with mode: 0644]
gtk/gtkbuilder.h [new file with mode: 0644]
gtk/gtkbuilderparser.c [new file with mode: 0644]
gtk/gtkbuilderprivate.h [new file with mode: 0644]
gtk/gtkcelllayout.c
gtk/gtkcelllayout.h
gtk/gtkcellview.c
gtk/gtkcolorseldialog.c
gtk/gtkcombobox.c
gtk/gtkcomboboxentry.c
gtk/gtkcontainer.c
gtk/gtkdebug.h
gtk/gtkdialog.c
gtk/gtkentrycompletion.c
gtk/gtkexpander.c
gtk/gtkfontsel.c
gtk/gtkframe.c
gtk/gtkiconview.c
gtk/gtkliststore.c
gtk/gtkmain.c
gtk/gtknotebook.c
gtk/gtksizegroup.c
gtk/gtktreestore.c
gtk/gtktreeview.c
gtk/gtktreeviewcolumn.c
gtk/gtkuimanager.c
gtk/gtkwidget.c
gtk/gtkwindow.c
tests/Makefile.am
tests/buildertest.c [new file with mode: 0644]

index 8e9869c70995041886ef2e604dd58c4594c06100..d97a89f3d1a6b6dad9b0ffc1c7a4ce7c13ecc860 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,152 @@
+2007-06-15  Johan Dahlin  <jdahlin@async.com.br>
+
+       reviewed by: Matthias Clasen
+
+       * demos/gtk-demo/Makefile.am:
+       * demos/gtk-demo/builder.c: (quit_activate), (about_activate),
+       (do_builder):
+       * demos/gtk-demo/demo.ui:
+       * docs/reference/gtk/gtk-docs.sgml:
+       * docs/reference/gtk/gtk-sections.txt:
+       * docs/reference/gtk/gtk.types:
+       * docs/reference/gtk/tmpl/gtkbuildable.sgml:
+       * docs/reference/gtk/tmpl/gtkbuilder.sgml:
+       * gtk/Makefile.am:
+       * gtk/gtk.h:
+       * gtk/gtk.symbols:
+       * gtk/gtkaction.c: (gtk_action_buildable_init),
+       (gtk_action_buildable_set_name), (gtk_action_buildable_get_name):
+       * gtk/gtkactiongroup.c: (gtk_action_group_get_type),
+       (gtk_action_group_buildable_init),
+       (gtk_action_group_buildable_add),
+       (gtk_action_group_buildable_set_name),
+       (gtk_action_group_buildable_get_name):
+       * gtk/gtkbuildable.c: (gtk_buildable_get_type),
+       (gtk_buildable_set_name), (gtk_buildable_get_name),
+       (gtk_buildable_add), (gtk_buildable_set_property),
+       (gtk_buildable_parser_finished), (gtk_buildable_construct_child),
+       (gtk_buildable_custom_tag_start), (gtk_buildable_custom_tag_end),
+       (gtk_buildable_custom_finished),
+       (gtk_buildable_get_internal_child):
+       * gtk/gtkbuildable.h:
+       * gtk/gtkbuilder.c: (gtk_builder_class_init), (gtk_builder_init),
+       (gtk_builder_finalize), (gtk_builder_set_property),
+       (gtk_builder_get_property), (_gtk_builder_resolve_type_lazily),
+       (gtk_builder_real_get_type_from_name),
+       (gtk_builder_get_parameters), (gtk_builder_get_internal_child),
+       (_gtk_builder_construct), (_gtk_builder_add),
+       (apply_delayed_properties), (_gtk_builder_finish),
+       (gtk_builder_new), (gtk_builder_add_from_file),
+       (gtk_builder_add_from_string), (gtk_builder_get_object),
+       (object_add_to_list), (gtk_builder_get_objects),
+       (gtk_builder_set_translation_domain),
+       (gtk_builder_get_translation_domain),
+       (gtk_builder_connect_signals_default),
+       (gtk_builder_connect_signals), (gtk_builder_connect_signals_full),
+       (gtk_builder_value_from_string),
+       (gtk_builder_value_from_string_type),
+       (_gtk_builder_enum_from_string), (_gtk_builder_flags_from_string),
+       (gtk_builder_get_type_from_name), (gtk_builder_error_quark):
+       * gtk/gtkbuilder.h:
+       * gtk/gtkbuilderparser.c: (state_push), (state_peek), (state_pop),
+       (error_missing_attribute), (error_invalid_attribute),
+       (error_invalid_tag), (builder_construct), (parse_object),
+       (free_object_info), (_get_type_by_symbol), (parse_child),
+       (free_child_info), (parse_property), (free_property_info),
+       (parse_signal), (_free_signal_info), (parse_interface),
+       (create_subparser), (free_subparser), (subparser_start),
+       (subparser_end), (parse_custom), (start_element), (end_element),
+       (text), (_gtk_builder_parser_parse_buffer):
+       * gtk/gtkbuilderprivate.h:
+       * gtk/gtkcelllayout.c: (attributes_start_element),
+       (attributes_text_element),
+       (_gtk_cell_layout_buildable_custom_tag_start),
+       (_gtk_cell_layout_buildable_custom_tag_end),
+       (_gtk_cell_layout_buildable_add):
+       * gtk/gtkcelllayout.h:
+       * gtk/gtkcellview.c: (gtk_cell_view_buildable_init),
+       (gtk_cell_view_buildable_custom_tag_start),
+       (gtk_cell_view_buildable_custom_tag_end):
+       * gtk/gtkcolorseldialog.c:
+       (gtk_color_selection_dialog_buildable_interface_init),
+       (gtk_color_selection_dialog_buildable_get_internal_child):
+       * gtk/gtkcombobox.c: (gtk_combo_box_buildable_init),
+       (gtk_combo_box_buildable_custom_tag_start),
+       (gtk_combo_box_buildable_custom_tag_end):
+       * gtk/gtkcomboboxentry.c:
+       (gtk_combo_box_entry_buildable_interface_init),
+       (gtk_combo_box_entry_buildable_get_internal_child):
+       * gtk/gtkcontainer.c: (gtk_container_get_type),
+       (gtk_container_buildable_init), (gtk_container_buildable_add),
+       (gtk_container_buildable_set_child_property),
+       (attributes_start_element), (attributes_text_element),
+       (gtk_container_buildable_custom_tag_start),
+       (gtk_container_buildable_custom_tag_end):
+       * gtk/gtkdebug.h:
+       * gtk/gtkdialog.c: (gtk_dialog_buildable_interface_init),
+       (gtk_dialog_buildable_get_internal_child),
+       (attributes_start_element), (attributes_text_element),
+       (gtk_dialog_buildable_custom_tag_start),
+       (gtk_dialog_buildable_custom_finished):
+       * gtk/gtkentrycompletion.c: (gtk_entry_completion_buildable_init):
+       * gtk/gtkexpander.c: (gtk_expander_buildable_add),
+       (gtk_expander_buildable_init):
+       * gtk/gtkfontsel.c:
+       (gtk_font_selection_dialog_buildable_interface_init),
+       (gtk_font_selection_dialog_buildable_get_internal_child):
+       * gtk/gtkframe.c: (gtk_frame_buildable_init),
+       (gtk_frame_buildable_add):
+       * gtk/gtkiconview.c: (gtk_icon_view_buildable_init),
+       (gtk_icon_view_buildable_custom_tag_start),
+       (gtk_icon_view_buildable_custom_tag_end):
+       * gtk/gtkliststore.c: (gtk_list_store_buildable_init),
+       (list_store_start_element), (list_store_end_element),
+       (list_store_text), (gtk_list_store_buildable_custom_tag_start),
+       (gtk_list_store_buildable_custom_tag_end):
+       * gtk/gtkmain.c:
+       * gtk/gtknotebook.c: (gtk_notebook_buildable_init),
+       (gtk_notebook_buildable_add):
+       * gtk/gtksizegroup.c: (gtk_size_group_buildable_init),
+       (size_group_start_element),
+       (gtk_size_group_buildable_custom_tag_start),
+       (gtk_size_group_buildable_custom_finished):
+       * gtk/gtktreestore.c: (gtk_tree_store_buildable_init),
+       (tree_model_start_element),
+       (gtk_tree_store_buildable_custom_tag_start),
+       (gtk_tree_store_buildable_custom_finished):
+       * gtk/gtktreeview.c: (gtk_tree_view_buildable_init),
+       (gtk_tree_view_buildable_add):
+       * gtk/gtktreeviewcolumn.c: (gtk_tree_view_column_buildable_init):
+       * gtk/gtkuimanager.c: (gtk_ui_manager_buildable_init),
+       (gtk_ui_manager_buildable_add),
+       (gtk_ui_manager_buildable_construct_child),
+       (gtk_ui_manager_buildable_custom_tag_start),
+       (gtk_ui_manager_buildable_custom_tag_end):
+       * gtk/gtkwidget.c: (gtk_widget_get_type),
+       (gtk_widget_buildable_interface_init),
+       (gtk_widget_buildable_set_name), (gtk_widget_buildable_get_name),
+       (gtk_widget_buildable_set_property),
+       (gtk_widget_buildable_parser_finshed), (accel_group_start_element),
+       (gtk_widget_buildable_custom_tag_start),
+       (gtk_widget_buildable_custom_finshed):
+       * gtk/gtkwindow.c: (gtk_window_buildable_interface_init),
+       (gtk_window_buildable_set_property),
+       (gtk_window_buildable_parser_finished):
+       * tests/Makefile.am:
+       * tests/buildertest.c: (builder_new_from_string), (test_parser),
+       (signal_normal), (signal_after), (signal_object),
+       (signal_object_after), (signal_first), (signal_second),
+       (signal_extra), (signal_extra2), (test_connect_signals),
+       (test_uimanager_simple), (test_domain), (test_translation),
+       (test_sizegroup), (test_list_store), (test_tree_store),
+       (test_types), (test_spin_button), (test_notebook),
+       (test_construct_only_property), (test_children),
+       (test_child_properties), (test_treeview_column), (test_icon_view),
+       (test_combo_box), (test_combo_box_entry), (test_cell_view),
+       (test_dialog), (test_accelerators), (test_widget), (main):
+
+       Add GtkBuilder, fixes #172535
+       
 2007-06-15  Hans Breuer <hans@breuer.org>
 
        * gtk/makefile.msc.in tests/makefile.msc : updated
index f043ee0f4eabaedd1d2c8d15e301edcd9a30b8c9..ccd941a0b83977d652b6b0728a3aa2842f4cbb85 100644 (file)
@@ -7,6 +7,7 @@ democodedir=$(datadir)/gtk-2.0/demo
 demos =                                                \
        appwindow.c                             \
        assistant.c                             \
+       builder.c                               \
        button_box.c                            \
        changedisplay.c                         \
        clipboard.c                             \
@@ -60,7 +61,8 @@ bin_PROGRAMS = gtk-demo
 BUILT_SOURCES = demos.h
 
 EXTRA_DIST =           \
-       $(IMAGEFILES)
+       $(IMAGEFILES)   \
+       demo.ui
 
 demos.h: @REBUILD@ $(demos) geninclude.pl
        (here=`pwd` ; cd $(srcdir) && $(PERL) $$here/geninclude.pl $(demos)) > demos.h
@@ -73,6 +75,7 @@ gtk_demo_SOURCES =            \
 
 gtk_demo_DEPENDENCIES = $(DEPS)
 gtk_demo_LDADD = $(LDADDS)
+gtk_demo_LDFLAGS = -export-dynamic
 
 IMAGEFILES=    alphatest.png           \
                apple-red.png           \
@@ -89,6 +92,6 @@ IMAGEFILES=   alphatest.png           \
                gnu-keys.png            \
                gtk-logo-rgb.gif                
 
-democode_DATA = $(demos) $(IMAGEFILES)
+democode_DATA = $(demos) $(IMAGEFILES) demo.ui
 
 DISTCLEANFILES = demos.h
diff --git a/demos/gtk-demo/builder.c b/demos/gtk-demo/builder.c
new file mode 100644 (file)
index 0000000..3363969
--- /dev/null
@@ -0,0 +1,60 @@
+/* Builder
+ *
+ * Demonstrates an interface loaded from a XML description.
+ */
+
+#include <gtk/gtk.h>
+#include "demo-common.h"
+
+void
+quit_activate (GtkAction *action)
+{
+}
+
+void
+about_activate (GtkAction *action)
+{
+  GtkWidget *about_dlg;
+
+  about_dlg = gtk_about_dialog_new ();
+  gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (about_dlg), "GtkBuilder demo");
+  gtk_dialog_run (GTK_DIALOG (about_dlg));
+  gtk_widget_destroy (about_dlg);
+}
+
+GtkWidget *
+do_builder (GtkWidget *do_widget)
+{
+  static GtkWidget *window = NULL;
+  GtkBuilder *builder;
+  GError *err = NULL;
+  gchar *filename;
+  
+  if (!window)
+    {
+      builder = gtk_builder_new ();
+      filename = demo_find_file ("demo.ui", NULL);
+      gtk_builder_add_from_file (builder, filename, &err);
+      g_free (filename);
+      if (err)
+       {
+         g_error ("ERROR: %s\n", err->message);
+         return NULL;
+       }
+      gtk_builder_connect_signals (builder, NULL);
+      window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
+    }
+
+  if (!GTK_WIDGET_VISIBLE (window))
+    {
+      gtk_widget_show_all (window);
+    }
+  else
+    {   
+      gtk_widget_destroy (window);
+      window = NULL;
+    }
+
+
+  return window;
+}
diff --git a/demos/gtk-demo/demo.ui b/demos/gtk-demo/demo.ui
new file mode 100644 (file)
index 0000000..9830ed9
--- /dev/null
@@ -0,0 +1,227 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<interface>
+    <object class="GtkListStore" id="liststore1">
+      <columns>
+        <column type="gchararray"/>
+        <column type="gchararray"/>
+        <column type="gint"/>
+      </columns>
+      <data>
+        <row>
+          <col id="0">John</col>
+          <col id="1">Doe</col>
+          <col id="2">25</col>
+        </row>
+        <row>
+          <col id="0">Mary</col>
+          <col id="1">Dole</col>
+          <col id="2">50</col>
+        </row>
+      </data>
+    </object>
+    <object class="GtkUIManager" id="uimanager">
+        <child>
+            <object class="GtkActionGroup" id="DefaultActions">
+                <child>
+                    <object class="GtkAction" id="Copy">
+                        <property name="name">Copy</property>
+                        <property name="tooltip" translatable="yes">Copy selected object into the clipboard</property>
+                        <property name="stock_id">gtk-copy</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Cut">
+                        <property name="name">Cut</property>
+                        <property name="tooltip" translatable="yes">Cut selected object into the clipboard</property>
+                        <property name="stock_id">gtk-cut</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="EditMenu">
+                        <property name="name">EditMenu</property>
+                        <property name="label" translatable="yes">_Edit</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="FileMenu">
+                        <property name="name">FileMenu</property>
+                        <property name="label" translatable="yes">_File</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="New">
+                        <property name="name">New</property>
+                        <property name="tooltip" translatable="yes">Create a new file</property>
+                        <property name="stock_id">gtk-new</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Open">
+                        <property name="name">Open</property>
+                        <property name="tooltip" translatable="yes">Open a file</property>
+                        <property name="stock_id">gtk-open</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Paste">
+                        <property name="name">Paste</property>
+                        <property name="tooltip" translatable="yes">Paste object from the Clipboard</property>
+                        <property name="stock_id">gtk-paste</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Quit">
+                        <property name="name">Quit</property>
+                        <property name="tooltip" translatable="yes">Quit the program</property>
+                        <property name="stock_id">gtk-quit</property>
+                        <signal handler="quit_activate" name="activate"/>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Save">
+                        <property name="name">Save</property>
+                        <property name="is_important">True</property>
+                        <property name="tooltip" translatable="yes">Save a file</property>
+                        <property name="stock_id">gtk-save</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="SaveAs">
+                        <property name="name">SaveAs</property>
+                        <property name="tooltip" translatable="yes">Save with a different name</property>
+                        <property name="stock_id">gtk-save-as</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="HelpMenu">
+                        <property name="name">Help</property>
+                        <property name="label" translatable="yes">_Help</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="About">
+                        <property name="name">About</property>
+                        <property name="stock_id">gtk-about</property>
+                        <signal handler="about_activate" name="activate"/>
+                    </object>
+                </child>
+            </object>
+        </child>
+        <ui>
+          <menubar name="menubar1">
+            <menu action="FileMenu" name="FileMenu">
+              <menuitem action="New" name="New"/>
+              <menuitem action="Open" name="Open"/>
+              <menuitem action="Save" name="Save"/>
+              <menuitem action="SaveAs" name="SaveAs"/>
+              <separator/>
+              <menuitem action="Quit" name="Quit"/>
+            </menu>
+            <menu action="EditMenu">
+              <menuitem action="Copy" name="Copy"/>
+              <menuitem action="Cut" name="Cut"/>
+              <menuitem action="Paste" name="Paste"/>
+            </menu>
+            <menu action="HelpMenu" name="HelpMenu">
+              <menuitem action="About" name="About"/>
+            </menu>
+          </menubar>
+          <toolbar name="toolbar1">
+            <toolitem action="New" name="New"/>
+            <toolitem action="Open" name="Open"/>
+            <toolitem action="Save" name="Save"/>
+            <separator/>
+            <toolitem action="Copy" name="Copy"/>
+            <toolitem action="Cut" name="Cut"/>
+            <toolitem action="Paste" name="Paste"/>
+          </toolbar>
+        </ui>
+    </object>
+
+    <object class="GtkWindow" id="window1">
+        <property name="default_height">250</property>
+        <property name="default_width">440</property>
+        <signal name="destroy" handler="gtk_widget_destroyed"/>
+        <child>
+            <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <child>
+                    <object constructor="uimanager" class="GtkMenuBar" id="menubar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                    </packing>
+                </child>
+                <child>
+                    <object constructor="uimanager" class="GtkToolbar" id="toolbar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                        <property name="position">1</property>
+                    </packing>
+                </child>
+                <child>
+                    <object class="GtkScrolledWindow" id="scrolledwindow1">
+                      <property name="hscrollbar_policy">automatic</property>
+                      <property name="shadow_type">in</property>
+                      <property name="visible">True</property>
+                      <property name="vscrollbar_policy">automatic</property>
+                      <child>
+                        <object class="GtkTreeView" id="treeview1">
+                          <property name="visible">True</property>
+                          <property name="model">liststore1</property>
+                          <child>
+                            <object class="GtkTreeViewColumn" id="column1">
+                              <property name="title">Name</property>
+                              <child>
+                                <object class="GtkCellRendererText" id="renderer1"/>
+                                <attributes>
+                                  <attribute name="text">0</attribute>
+                                </attributes>
+                              </child>
+                            </object>
+                          </child>
+                          <child>
+                            <object class="GtkTreeViewColumn" id="column2">
+                              <property name="title">Surname</property>
+                              <child>
+                                <object class="GtkCellRendererText" id="renderer2"/>
+                                <attributes>
+                                  <attribute name="text">1</attribute>
+                                </attributes>
+                              </child>
+                            </object>
+                          </child>
+                          <child>
+                            <object class="GtkTreeViewColumn" id="column3">
+                              <property name="title">Age</property>
+                              <child>
+                                <object class="GtkCellRendererText" id="renderer3"/>
+                                <attributes>
+                                  <attribute name="text">2</attribute>
+                                </attributes>
+                              </child>
+                            </object>
+                          </child>
+                        </object>
+                      </child>
+                    </object>
+                    <packing>
+                        <property name="position">2</property>
+                    </packing>
+                </child>
+                <child>
+                    <object class="GtkStatusbar" id="statusbar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                        <property name="position">3</property>
+                    </packing>
+                </child>
+            </object>
+        </child>
+    </object>
+</interface>
index dfa7bd4cda16797eb39942ac7c0b91852497f736..f50d84383653a52de510d952f0ca5d945b8f021f 100644 (file)
@@ -14,6 +14,8 @@
 <!ENTITY GtkBin SYSTEM "xml/gtkbin.xml">
 <!ENTITY GtkBox SYSTEM "xml/gtkbox.xml">
 <!ENTITY GtkButton SYSTEM "xml/gtkbutton.xml">
+<!ENTITY GtkBuildable SYSTEM "xml/gtkbuildable.xml">
+<!ENTITY GtkBuilder SYSTEM "xml/gtkbuilder.xml">
 <!ENTITY GtkCalendar SYSTEM "xml/gtkcalendar.xml">
 <!ENTITY GtkCheckButton SYSTEM "xml/gtkcheckbutton.xml">
 <!ENTITY GtkCheckMenuItem SYSTEM "xml/gtkcheckmenuitem.xml">
@@ -588,6 +590,12 @@ that is, GUI components such as #GtkButton or #GtkTextView.
       &GtkRecentFilter;
     </chapter>
 
+    <chapter id="Builder">
+      <title>Interface builder</title>
+      &GtkBuildable;
+      &GtkBuilder;
+    </chapter>
+
     <chapter id="DeprecatedObjects">
       <title>Deprecated</title>
         &GtkCList;      
index 5aed8ff2350db87e15f7e85813c4bce5d255c13b..b41ab7e3b272332be89ca2d463fd8463c3fafe00 100644 (file)
@@ -431,6 +431,73 @@ GTK_BOX_GET_CLASS
 gtk_box_get_type
 </SECTION>
 
+<SECTION>
+<FILE>gtkvscrollbar</FILE>
+<TITLE>GtkVScrollbar</TITLE>
+GtkVScrollbar
+gtk_vscrollbar_new
+<SUBSECTION Standard>
+GTK_VSCROLLBAR
+GTK_IS_VSCROLLBAR
+GTK_TYPE_VSCROLLBAR
+gtk_vscrollbar_get_type
+GTK_VSCROLLBAR_CLASS
+GTK_IS_VSCROLLBAR_CLASS
+GTK_VSCROLLBAR_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gtkbuildable</FILE>
+GtkBuildable
+GtkBuildableIface
+gtk_buildable_set_name
+gtk_buildable_get_name
+gtk_buildable_add
+gtk_buildable_set_property
+gtk_buildable_construct_child
+gtk_buildable_custom_tag_start
+gtk_buildable_custom_tag_end
+gtk_buildable_custom_finished
+gtk_buildable_parser_finished
+gtk_buildable_get_internal_child
+<SUBSECTION Standard>
+GTK_BUILDABLE
+GTK_IS_BUILDABLE
+GTK_TYPE_BUILDABLE
+gtk_buildable_get_type
+GTK_BUILDABLE_CLASS
+GTK_BUILDABLE_GET_IFACE
+</SECTION>
+
+<SECTION>
+<FILE>gtkbuilder</FILE>
+<TITLE>GtkBuilder</TITLE>
+GtkBuilder
+GtkBuilderConnectFunc
+gtk_builder_new
+gtk_builder_add_from_file
+gtk_builder_add_from_string
+gtk_builder_get_object
+gtk_builder_get_objects
+gtk_builder_connect_signals
+gtk_builder_connect_signals_full
+gtk_builder_set_translation_domain
+gtk_builder_get_translation_domain
+gtk_builder_get_type_from_name
+gtk_builder_value_from_string
+gtk_builder_value_from_string_type
+GTK_BUILDER_WARN_INVALID_CHILD_TYPE
+<SUBSECTION Standard>
+GTK_BUILDER
+GTK_IS_BUILDER
+GTK_TYPE_BUILDER
+GTK_BUILDER_CLASS
+GTK_IS_BUILDER_CLASS
+GTK_BUILDER_GET_CLASS
+<SUBSECTION Private>
+gtk_builder_get_type
+</SECTION>
+
 <SECTION>
 <FILE>gtkbutton</FILE>
 <TITLE>GtkButton</TITLE>
index 5ad47ff551ec7d296460b6c1d7fe8ae8b36cfc16..fde19eae171aa9e82e2f7cb5a03c2c8c492d7d58 100644 (file)
@@ -18,6 +18,8 @@ gtk_aspect_frame_get_type
 gtk_assistant_get_type
 gtk_bin_get_type
 gtk_box_get_type
+gtk_builder_get_type
+gtk_buildable_get_type
 gtk_button_box_get_type
 gtk_button_get_type
 gtk_calendar_get_type
diff --git a/docs/reference/gtk/tmpl/gtkbuildable.sgml b/docs/reference/gtk/tmpl/gtkbuildable.sgml
new file mode 100644 (file)
index 0000000..8080455
--- /dev/null
@@ -0,0 +1,151 @@
+<!-- ##### SECTION Title ##### -->
+GtkBuildable
+
+<!-- ##### SECTION Short_Description ##### -->
+SHORT
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+LONG
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+SEE ALSO
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT GtkBuildable ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT GtkBuildableIface ##### -->
+<para>
+
+</para>
+
+@g_iface: 
+@set_name: 
+@get_name: 
+@add: 
+@set_property: 
+@construct_child: 
+@custom_tag_start: 
+@custom_tag_end: 
+@custom_finished: 
+@parser_finished: 
+@get_internal_child: 
+
+<!-- ##### FUNCTION gtk_buildable_set_name ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@name: 
+
+
+<!-- ##### FUNCTION gtk_buildable_get_name ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_buildable_add ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@child: 
+@type: 
+
+
+<!-- ##### FUNCTION gtk_buildable_set_property ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@name: 
+@value: 
+
+
+<!-- ##### FUNCTION gtk_buildable_construct_child ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@name: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_buildable_custom_tag_start ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@child: 
+@tagname: 
+@parser: 
+@data: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_buildable_custom_tag_end ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@child: 
+@tagname: 
+@data: 
+
+
+<!-- ##### FUNCTION gtk_buildable_custom_finished ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@child: 
+@tagname: 
+@data: 
+
+
+<!-- ##### FUNCTION gtk_buildable_parser_finished ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+
+
+<!-- ##### FUNCTION gtk_buildable_get_internal_child ##### -->
+<para>
+
+</para>
+
+@buildable: 
+@builder: 
+@childname: 
+@Returns: 
+
+
diff --git a/docs/reference/gtk/tmpl/gtkbuilder.sgml b/docs/reference/gtk/tmpl/gtkbuilder.sgml
new file mode 100644 (file)
index 0000000..34b8a2d
--- /dev/null
@@ -0,0 +1,181 @@
+<!-- ##### SECTION Title ##### -->
+GtkBuilder
+
+<!-- ##### SECTION Short_Description ##### -->
+Build an interface from a UI definition description.
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+This object represents an `instantiation' of an UI definition description. 
+When one of these objects is created, the XML file is read, and the 
+interface is created. The GtkBuilder object then provides an interface 
+for accessing the widgets in the interface by the names assigned to 
+them inside the UI description.
+
+The GtkBuilder object can also be used to connect handlers to the named 
+signals in the description. GtkBuilder also provides an interface by 
+which it can look up the signal handler names in the program's symbol 
+table and automatically connect as many handlers up as it can that way.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+SEE ALSO
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT GtkBuilder ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkBuilder:translation-domain ##### -->
+<para>
+
+</para>
+
+<!-- ##### USER_FUNCTION GtkBuilderConnectFunc ##### -->
+<para>
+
+</para>
+
+@builder: 
+@object: 
+@signal_name: 
+@handler_name: 
+@connect_object: 
+@flags: 
+@user_data: 
+
+
+<!-- ##### FUNCTION gtk_builder_new ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_add_from_file ##### -->
+<para>
+
+</para>
+
+@builder: 
+@filename: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_add_from_string ##### -->
+<para>
+
+</para>
+
+@builder: 
+@buffer: 
+@length: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_get_object ##### -->
+<para>
+
+</para>
+
+@builder: 
+@name: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_get_objects ##### -->
+<para>
+
+</para>
+
+@builder: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_connect_signals ##### -->
+<para>
+
+</para>
+
+@builder: 
+@user_data: 
+
+
+<!-- ##### FUNCTION gtk_builder_connect_signals_full ##### -->
+<para>
+
+</para>
+
+@builder: 
+@func: 
+@user_data: 
+
+
+<!-- ##### FUNCTION gtk_builder_set_translation_domain ##### -->
+<para>
+
+</para>
+
+@builder: 
+@domain: 
+
+
+<!-- ##### FUNCTION gtk_builder_get_translation_domain ##### -->
+<para>
+
+</para>
+
+@builder: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_get_type_from_name ##### -->
+<para>
+
+</para>
+
+@builder: 
+@typename: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_value_from_string ##### -->
+<para>
+
+</para>
+
+@pspec: 
+@string: 
+@value: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_builder_value_from_string_type ##### -->
+<para>
+
+</para>
+
+@type: 
+@string: 
+@value: 
+@Returns: 
+
+
+<!-- ##### MACRO GTK_BUILDER_WARN_INVALID_CHILD_TYPE ##### -->
+<para>
+
+</para>
+
+@object: 
+@type: 
+
+
index a1acb56cdc53c8949c4306f56ad50f43e6df7902..92a78b8537c71def67dd68caa56d744b43e8a646 100644 (file)
@@ -143,6 +143,9 @@ gtk_public_h_sources =          \
        gtkbin.h                \
        gtkbindings.h           \
        gtkbox.h                \
+       gtkbuilder.h            \
+       gtkbuildable.h          \
+       gtkbuilderprivate.h     \
        gtkbutton.h             \
        gtkcalendar.h           \
        gtkcelleditable.h       \
@@ -405,6 +408,9 @@ gtk_base_c_sources =            \
        gtkbin.c                \
        gtkbindings.c           \
        gtkbox.c                \
+       gtkbuildable.c          \
+       gtkbuilder.c            \
+       gtkbuilderparser.c      \
        gtkbutton.c             \
        gtkcalendar.c           \
        gtkcelleditable.c       \
index 1e9436fb5f6d5f69bbcb040384b5684ac60a4d05..70f04b79846b02b0a712eb96501942fee43e2b56 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -45,6 +45,7 @@
 #include <gtk/gtkbin.h>
 #include <gtk/gtkbindings.h>
 #include <gtk/gtkbox.h>
+#include <gtk/gtkbuildable.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkcalendar.h>
 #include <gtk/gtkcelllayout.h>
index 4cff2b5640e1049a6b558053f67491739b68703c..0ad3de6148d07aaf41c24ecd1ff27bd1dd8600e6 100644 (file)
@@ -254,6 +254,7 @@ gtk_arg_flags_get_type G_GNUC_CONST
 gtk_arrow_type_get_type G_GNUC_CONST
 gtk_assistant_page_type_get_type G_GNUC_CONST
 gtk_attach_options_get_type G_GNUC_CONST
+gtk_builder_error_get_type G_GNUC_CONST
 gtk_button_action_get_type G_GNUC_CONST
 gtk_buttons_type_get_type G_GNUC_CONST
 gtk_calendar_display_options_get_type G_GNUC_CONST
@@ -420,6 +421,41 @@ gtk_box_set_spacing
 #endif
 #endif
 
+#if IN_HEADER(__GTK_BUILDABLE_H__)
+#if IN_FILE(__GTK_BUILDABLE_C__)
+gtk_buildable_add
+gtk_buildable_construct_child
+gtk_buildable_custom_tag_start
+gtk_buildable_custom_tag_end
+gtk_buildable_custom_finished
+gtk_buildable_get_internal_child
+gtk_buildable_get_name
+gtk_buildable_get_type G_GNUC_CONST
+gtk_buildable_parser_finished
+gtk_buildable_set_name
+gtk_buildable_set_property
+#endif
+#endif
+
+#if IN_HEADER(__GTK_BUILDER_H__)
+#if IN_FILE(__GTK_BUILDER_C__)
+gtk_builder_add_from_file
+gtk_builder_add_from_string
+gtk_builder_error_quark
+gtk_builder_get_object
+gtk_builder_get_objects
+gtk_builder_get_translation_domain
+gtk_builder_get_type G_GNUC_CONST
+gtk_builder_get_type_from_name
+gtk_builder_new
+gtk_builder_set_translation_domain
+gtk_builder_connect_signals
+gtk_builder_connect_signals_full
+gtk_builder_value_from_string
+gtk_builder_value_from_string_type
+#endif
+#endif
+
 #if IN_HEADER(__GTK_BUTTON_BOX_H__)
 #if IN_FILE(__GTK_BUTTON_BOX_C__)
 #ifndef GTK_DISABLE_DEPRECATED
index eb8173ef8b244d8c5bdd42511bf438e616a37855..f1b161820ea43036f0e60e297cebdf1eaf742587 100644 (file)
@@ -46,6 +46,7 @@
 #include "gtktoolbutton.h"
 #include "gtktoolbar.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 
@@ -107,14 +108,22 @@ enum
   PROP_ACTION_GROUP
 };
 
+/* GtkBuildable */
+static void gtk_action_buildable_init             (GtkBuildableIface *iface);
+static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
+                                                  const gchar  *name);
+static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
+
+G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_action_buildable_init))
+
 
 static GQuark      accel_path_id  = 0;
 static GQuark      quark_gtk_action_proxy  = 0;
 static const gchar accel_path_key[] = "GtkAction::accel_path";
 static const gchar gtk_action_proxy_key[] = "gtk-action";
 
-G_DEFINE_TYPE (GtkAction, gtk_action, G_TYPE_OBJECT)
-
 static void gtk_action_finalize     (GObject *object);
 static void gtk_action_set_property (GObject         *object,
                                     guint            prop_id,
@@ -378,6 +387,33 @@ gtk_action_init (GtkAction *action)
   action->private_data->proxies = NULL;
 }
 
+static void
+gtk_action_buildable_init (GtkBuildableIface *iface)
+{
+  iface->set_name = gtk_action_buildable_set_name;
+  iface->get_name = gtk_action_buildable_get_name;
+}
+
+static void
+gtk_action_buildable_set_name (GtkBuildable *buildable,
+                              const gchar  *name)
+{
+  gchar *tmp;
+  GtkAction *action = GTK_ACTION (buildable);
+
+  tmp = action->private_data->name;
+  action->private_data->name = g_strdup (name);
+  g_free (tmp);
+}
+
+static const gchar *
+gtk_action_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkAction *action = GTK_ACTION (buildable);
+
+  return action->private_data->name;
+}
+
 /**
  * gtk_action_new:
  * @name: A unique name for the action
index 26243f31975917fcbe646e2a0b500715b3a4a85c..c976b46e1145e340d3a59d081a941ad1ed888190 100644 (file)
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include "gtkactiongroup.h"
+#include "gtkbuildable.h"
 #include "gtkiconfactory.h"
 #include "gtkicontheme.h"
 #include "gtkstock.h"
@@ -87,6 +88,15 @@ static void       gtk_action_group_get_property    (GObject             *object,
 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup      *self,
                                                    const gchar         *name);
 
+/* GtkBuildable */
+static void gtk_action_group_buildable_init (GtkBuildableIface *iface);
+static void gtk_action_group_buildable_add (GtkBuildable  *buildable,
+                                           GtkBuilder    *builder,
+                                           GObject       *child,
+                                           const gchar   *type);
+static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+                                                const gchar  *name);
+static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable);
 
 GType
 gtk_action_group_get_type (void)
@@ -108,10 +118,20 @@ gtk_action_group_get_type (void)
         (GInstanceInitFunc) gtk_action_group_init,
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+       (GInterfaceInitFunc) gtk_action_group_buildable_init,
+       NULL,
+       NULL
+      };
+
       type = g_type_register_static (G_TYPE_OBJECT, I_("GtkActionGroup"),
                                     &type_info, 0);
-    }
 
+      g_type_add_interface_static (type,
+                                  GTK_TYPE_BUILDABLE,
+                                  &buildable_info);
+    }
   return type;
 }
 
@@ -272,6 +292,39 @@ gtk_action_group_init (GtkActionGroup *self)
   self->private_data->translate_notify = NULL;
 }
 
+static void
+gtk_action_group_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_action_group_buildable_add;
+  iface->set_name = gtk_action_group_buildable_set_name;
+  iface->get_name = gtk_action_group_buildable_get_name;
+}
+
+static void
+gtk_action_group_buildable_add (GtkBuildable  *buildable,
+                               GtkBuilder    *builder,
+                               GObject       *child,
+                               const gchar   *type)
+{
+  gtk_action_group_add_action (GTK_ACTION_GROUP (buildable),
+                              GTK_ACTION (child));
+}
+
+static void
+gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+                                    const gchar  *name)
+{
+  GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+  self->private_data->name = g_strdup (name);
+}
+
+static const gchar *
+gtk_action_group_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+  return self->private_data->name;
+}
+
 /**
  * gtk_action_group_new:
  * @name: the name of the action group.
diff --git a/gtk/gtkbuildable.c b/gtk/gtkbuildable.c
new file mode 100644 (file)
index 0000000..ee3934e
--- /dev/null
@@ -0,0 +1,372 @@
+/* gtkbuildable.c
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include "gtkbuildable.h"
+#include "gtktypeutils.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+GType
+gtk_buildable_get_type (void)
+{
+  static GType buildable_type = 0;
+
+  if (!buildable_type)
+    buildable_type =
+      g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkBuildable"),
+                                    sizeof (GtkBuildableIface),
+                                    NULL, 0, NULL, 0);
+
+  return buildable_type;
+}
+
+/**
+ * gtk_buildable_set_name:
+ * @buildable: a #GtkBuildable
+ * @name: name to set
+ *
+ * Sets the name of the buildable object, it's used to synchronize the name
+ * if the object already has it's own concept of name.
+ *
+ * #GtkWidget implements this to map the buildable name to the widget name
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_set_name (GtkBuildable *buildable,
+                        const gchar  *name)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (name != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  if (iface->set_name)
+    (* iface->set_name) (buildable, name);
+  else
+    g_object_set_data_full (G_OBJECT (buildable),
+                           "gtk-builder-name",
+                           g_strdup (name),
+                           g_free);
+}
+
+/**
+ * gtk_buildable_get_name:
+ * @buildable: a #GtkBuildable
+ *
+ * Returns: the buildable name, the name which was set in
+ * the <link linkend="BUILDER-UI">GtkBuilder UI definition</link> used to
+ * construct the @buildable.
+ *
+ * #GtkWidget implements this to map the buildable name to the widget name
+ *
+ * Since: 2.12
+ **/
+const gchar *
+gtk_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  if (iface->get_name)
+    return (* iface->get_name) (buildable);
+  else
+    return (const gchar*)g_object_get_data (G_OBJECT (buildable),
+                                           "gtk-builder-name");
+}
+
+/**
+ * gtk_buildable_add:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @child: child to add
+ * @type: kind of child or %NULL
+ *
+ * Add a child to a buildable. type is an optional string
+ * describing how the child should be added.
+ *
+ * #GtkContainer implements this to be able to add a child widget
+ * to the container. #GtkNotebook uses the @type to distinguish between
+ * page labels (@type = "page-label") and normal children.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_add (GtkBuildable *buildable,
+                   GtkBuilder   *builder,
+                   GObject      *child,
+                   const gchar  *type)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_if_fail (iface->add != NULL);
+
+  (* iface->add) (buildable, builder, child, type);
+}
+
+/**
+ * gtk_buildable_set_property:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @name: name of property
+ * @value: value of property
+ *
+ * Sets the property name @name to @value on the buildable object @buildable
+ * which is created by the @builder.
+ *
+ * This is optional to implement and is normally not needed.
+ * g_object_set_property() is used as a fallback.
+ *
+ * #GtkWindow implements this to delay showing (::visible) itself until
+ * the whole interface is fully created.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_set_property (GtkBuildable *buildable,
+                            GtkBuilder   *builder,
+                            const gchar  *name,
+                            const GValue *value)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (value != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->set_property)
+    (* iface->set_property) (buildable, builder, name, value);
+  else
+    g_object_set_property (G_OBJECT (buildable), name, value);
+}
+
+/**
+ * gtk_buildable_parser_finished:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ *
+ * Finish the parsing of a <link linkend="BUILDER-UI">GtkBuilder UI definition</link>
+ * snippet. Note that this will be called once for each time gtk_builder_add_from_file or
+ * gtk_builder_add_from_string is called on a builder.
+ *
+ * #GtkWindow implements this to delay showing (::visible) itself until
+ * the whole interface is fully created.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_parser_finished (GtkBuildable *buildable,
+                              GtkBuilder   *builder)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->parser_finished)
+    (* iface->parser_finished) (buildable, builder);
+}
+
+/**
+ * gtk_buildable_construct_child
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @name: name of child to construct
+ *
+ * Construct a child of @buildable with the name @name.
+ *
+ * #GtkUIManager implements this to reference to a widget created in a &lt;ui&gt; tag
+ * which is outside of the normal <link linkend="BUILDER-UI">GtkBuilder UI definition</link>
+ * object hierarchy.
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_buildable_construct_child (GtkBuildable *buildable,
+                               GtkBuilder   *builder,
+                               const gchar  *name)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_val_if_fail (iface->construct_child != NULL, NULL);
+
+  return (* iface->construct_child) (buildable, builder, name);
+}
+
+/**
+ * gtk_buildable_custom_tag_start
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder used to construct this object
+ * @child: child object or %NULL for non-child tags
+ * @tagname: name of tag
+ * @parser: a #GMarkupParser structure
+ * @data: user data that will be passed in to parser functions
+ *
+ * This is called when an unknown tag under &lt;child&gt; tag is found.
+ * 
+ * Called when an unknown tag is present under a &lt;child&gt; tag.
+ * If the buildable implementation wishes to handle the tag it should
+ * return %TRUE and fill in the @parser structure. Remember to either
+ * implement custom_tag_end or custom_tag_finish to free
+ * the user data allocated here.
+ *
+ * #GtkWidget implements this and parsers all &lt;accelerator&gt; tags to
+ * keyboard accelerators.
+ * #GtkContainer implements this to map properties defined under
+ * &lt;packing&gt; tag to child properties.
+ *
+ * Returns: %TRUE if a object has a custom implementation, %FALSE
+ *          if it doesn't.
+ *
+ * Since: 2.12
+ **/
+gboolean
+gtk_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                GtkBuilder    *builder,
+                                GObject       *child,
+                                const gchar   *tagname,
+                                GMarkupParser *parser,
+                                gpointer      *data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), FALSE);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
+  g_return_val_if_fail (tagname != NULL, FALSE);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_val_if_fail (iface->custom_tag_start != NULL, FALSE);
+
+  return (* iface->custom_tag_start) (buildable, builder, child,
+                                      tagname, parser, data);
+}
+
+/**
+ * gtk_buildable_custom_tag_end
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @child: child object or %NULL for non-child tags
+ * @tagname: name of tag
+ * @data: user data that will be passed in to parser functions
+ *
+ * This is called for each custom tag handled by the buildable.
+ * It will be called when the end of the tag is reached.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_custom_tag_end (GtkBuildable  *buildable,
+                              GtkBuilder    *builder,
+                              GObject       *child,
+                              const gchar   *tagname,
+                              gpointer      *data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (tagname != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->custom_tag_end)
+    (* iface->custom_tag_end) (buildable, builder, child, tagname, data);
+}
+
+/**
+ * gtk_buildable_custom_finished:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @child: child object or %NULL for non-child tags
+ * @tagname: the name of the tag
+ * @data: user data created in custom_tag_start
+ *
+ * This is similar to gtk_buildable_parser_finished() but is
+ * called once for each custom tag handled by the @buildable.
+ * 
+ * Since: 2.12
+ **/
+void
+gtk_buildable_custom_finished (GtkBuildable  *buildable,
+                              GtkBuilder    *builder,
+                              GObject       *child,
+                              const gchar   *tagname,
+                              gpointer       data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->custom_finished)
+    (* iface->custom_finished) (buildable, builder, child, tagname, data);
+}
+
+/**
+ * gtk_buildable_get_internal_child
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @childname: name of child
+ *
+ * Get the internal child called @child of the @buildable object.
+ *
+ * Return: the internal child of the buildable object
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_buildable_get_internal_child (GtkBuildable *buildable,
+                                  GtkBuilder   *builder,
+                                  const gchar  *childname)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (childname != NULL, NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (!iface->get_internal_child)
+    return NULL;
+
+  return (* iface->get_internal_child) (buildable, builder, childname);
+}
+
+#define __GTK_BUILDABLE_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkbuildable.h b/gtk/gtkbuildable.h
new file mode 100644 (file)
index 0000000..397e4e8
--- /dev/null
@@ -0,0 +1,123 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDABLE_H__
+#define __GTK_BUILDABLE_H__
+
+#include <glib/gmarkup.h>
+#include <gtk/gtkbuilder.h>
+#include <gtk/gtktypeutils.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDABLE            (gtk_buildable_get_type ())
+#define GTK_BUILDABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildable))
+#define GTK_BUILDABLE_CLASS(obj)      (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+#define GTK_IS_BUILDABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDABLE))
+#define GTK_BUILDABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+
+typedef struct _GtkBuildable      GtkBuildable; /* Dummy typedef */
+typedef struct _GtkBuildableIface GtkBuildableIface;
+
+struct _GtkBuildableIface
+{
+  GTypeInterface g_iface;
+
+  /* virtual table */
+  void          (* set_name)            (GtkBuildable  *buildable,
+                                         const gchar   *name);
+  const gchar * (* get_name)            (GtkBuildable  *buildable);
+  void          (* add)                 (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *type);
+  void          (* set_property)        (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *name,
+                                         const GValue  *value);
+  GObject *     (* construct_child)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *name);
+  gboolean      (* custom_tag_start)    (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data);
+  void          (* custom_tag_end)      (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         gpointer      *data);
+  void          (* custom_finished)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         gpointer       data);
+  void          (* parser_finished)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder);
+
+  GObject *    (* get_internal_child)   (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *childname);
+};
+
+
+GType     gtk_buildable_get_type           (void) G_GNUC_CONST;
+
+void      gtk_buildable_set_name           (GtkBuildable        *buildable,
+                                            const gchar         *name);
+const gchar * gtk_buildable_get_name       (GtkBuildable        *buildable);
+void      gtk_buildable_add                (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *type);
+void      gtk_buildable_set_property       (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *name,
+                                            const GValue        *value);
+GObject * gtk_buildable_construct_child    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *name);
+gboolean  gtk_buildable_custom_tag_start   (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            GMarkupParser       *parser,
+                                            gpointer            *data);
+void      gtk_buildable_custom_tag_end     (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            gpointer            *data);
+void      gtk_buildable_custom_finished    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            gpointer             data);
+void      gtk_buildable_parser_finished    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder);
+GObject * gtk_buildable_get_internal_child (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *childname);
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDABLE_H__ */
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
new file mode 100644 (file)
index 0000000..a4017c3
--- /dev/null
@@ -0,0 +1,1267 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998-2002 James Henstridge <james@daa.com.au>
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>,
+ *                         Henrique Romano <henrique@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <ctype.h> /* tolower, toupper */
+#include <errno.h> /* errno */
+#include <stdlib.h> /* strtol, strtoul */
+#include <string.h> /* strlen */
+
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkbuilderprivate.h"
+#include "gtkmain.h"
+#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtktypebuiltins.h"
+#include "gtkalias.h"
+
+static void gtk_builder_class_init     (GtkBuilderClass *klass);
+static void gtk_builder_init           (GtkBuilder      *builder);
+static void gtk_builder_finalize       (GObject         *object);
+static void gtk_builder_set_property   (GObject         *object,
+                                        guint            prop_id,
+                                        const GValue    *value,
+                                        GParamSpec      *pspec);
+static void gtk_builder_get_property   (GObject         *object,
+                                        guint            prop_id,
+                                        GValue          *value,
+                                        GParamSpec      *pspec);
+static GType gtk_builder_real_get_type_from_name   (GtkBuilder      *builder,
+                                                    const char      *typename);
+static gint _gtk_builder_enum_from_string (GType type, const char *string);
+
+
+enum {
+  PROP_0,
+  PROP_TRANSLATION_DOMAIN,
+};
+
+struct _GtkBuilderPrivate
+{
+  gchar *domain;
+  GHashTable *objects;
+  GHashTable *delayed_properties;
+  GSList *signals;
+  gchar *current_toplevel;
+};
+
+G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
+
+static void
+gtk_builder_class_init (GtkBuilderClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gtk_builder_finalize;
+  gobject_class->set_property = gtk_builder_set_property;
+  gobject_class->get_property = gtk_builder_get_property;
+
+  klass->get_type_from_name = gtk_builder_real_get_type_from_name;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TRANSLATION_DOMAIN,
+                                   g_param_spec_string ("translation-domain",
+                                                        P_("Translation Domain"),
+                                                        P_("The translation domain used by gettext"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+
+  g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
+}
+
+static void
+gtk_builder_init (GtkBuilder *builder)
+{
+  builder->priv = G_TYPE_INSTANCE_GET_PRIVATE (builder, GTK_TYPE_BUILDER,
+                                               GtkBuilderPrivate);
+  builder->priv->domain = NULL;
+  builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  g_free, NULL);
+  builder->priv->delayed_properties = g_hash_table_new_full (g_str_hash,
+                                                             g_str_equal,
+                                                             g_free, NULL);
+}
+
+
+/*
+ * GObject virtual methods
+ */
+
+static void
+gtk_builder_finalize (GObject *object)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+  
+  g_free (builder->priv->domain);
+
+  g_free (builder->priv->current_toplevel);
+  g_hash_table_destroy (builder->priv->delayed_properties);
+  builder->priv->delayed_properties = NULL;
+  g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (builder->priv->signals);
+  g_hash_table_destroy (builder->priv->objects);
+}
+
+static void
+gtk_builder_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TRANSLATION_DOMAIN:
+      gtk_builder_set_translation_domain (builder, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_builder_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TRANSLATION_DOMAIN:
+      g_value_set_string (value, builder->priv->domain);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+/*
+ * Try to map a type name to a _get_type function
+ * and call it, eg:
+ *
+ * GtkWindow -> gtk_window_get_type
+ * GtkHBox -> gtk_hbox_get_type
+ * GtkUIManager -> gtk_ui_manager_get_type
+ *
+ */
+static GType
+_gtk_builder_resolve_type_lazily (const gchar *name)
+{
+  static GModule *module = NULL;
+  GTypeGetFunc func;
+  GString *symbol_name = g_string_new ("");
+  char c, *symbol;
+  int i;
+  GType gtype = G_TYPE_INVALID;
+
+  if (!module)
+    module = g_module_open (NULL, 0);
+  
+  for (i = 0; name[i] != '\0'; i++)
+    {
+      c = name[i];
+      /* skip if uppercase, first or previous is uppercase */
+      if ((c == toupper (c) &&
+           i > 0 && name[i-1] != toupper (name[i-1])) ||
+          (i > 2 && name[i]   == toupper (name[i]) &&
+           name[i-1] == toupper (name[i-1]) &&
+           name[i-2] == toupper (name[i-2])))
+        g_string_append_c (symbol_name, '_');
+      g_string_append_c (symbol_name, tolower (c));
+    }
+  g_string_append (symbol_name, "_get_type");
+  
+  symbol = g_string_free (symbol_name, FALSE);
+
+  if (g_module_symbol (module, symbol, (gpointer)&func))
+    gtype = func ();
+  
+  g_free (symbol);
+
+  return gtype;
+}
+
+/*
+ * GtkBuilder virtual methods
+ */
+
+static GType
+gtk_builder_real_get_type_from_name (GtkBuilder *builder, const char *typename)
+{
+  GType gtype;
+
+  gtype = g_type_from_name (typename);
+  if (gtype != G_TYPE_INVALID)
+    return gtype;
+
+  return _gtk_builder_resolve_type_lazily (typename);
+}
+
+typedef struct
+{
+  gchar *object;
+  gchar *name;
+  gchar *value;
+} DelayedProperty;
+
+static void
+gtk_builder_get_parameters (GtkBuilder  *builder,
+                            GType        object_type,
+                            const gchar *object_name,
+                            GSList      *properties,
+                            GArray      **parameters,
+                            GArray      **construct_parameters)
+{
+  GSList *l;
+  GParamSpec *pspec;
+  GObjectClass *oclass;
+  DelayedProperty *property;
+
+  oclass = g_type_class_ref (object_type);
+  g_assert (oclass != NULL);
+
+  *parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
+  *construct_parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
+
+  for (l = properties; l; l = l->next)
+    {
+      PropertyInfo *prop = (PropertyInfo*)l->data;
+      GParameter parameter = { NULL };
+
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
+                                            prop->name);
+      if (!pspec)
+        {
+          g_warning ("Unknown property: %s.%s\n",
+                     g_type_name (object_type), prop->name);
+          continue;
+        }
+
+      parameter.name = prop->name;
+
+      if (G_IS_PARAM_SPEC_OBJECT (pspec))
+        {
+          if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+            {
+              GObject *object;
+              object = gtk_builder_get_object (builder, prop->data);
+              if (!object)
+                {
+                  g_warning ("failed to get constuct only property %s of %s "
+                             "with value `%s'",
+                             prop->name, object_name, prop->data);
+                  continue;
+                }
+              g_value_init (&parameter.value, G_OBJECT_TYPE (object));
+              g_value_set_object (&parameter.value, g_object_ref (object));
+            }
+          else
+            {
+              GSList *delayed_properties;
+              
+              delayed_properties = g_hash_table_lookup (builder->priv->delayed_properties,
+                                                        builder->priv->current_toplevel);
+              property = g_slice_new (DelayedProperty);
+              property->object = g_strdup (object_name);
+              property->name = g_strdup (prop->name);
+              property->value = g_strdup (prop->data);
+              delayed_properties = g_slist_prepend (delayed_properties, property);
+              g_hash_table_insert (builder->priv->delayed_properties,
+                                   g_strdup (builder->priv->current_toplevel),
+                                   delayed_properties);
+              continue;
+            }
+        }
+      else if (!gtk_builder_value_from_string (pspec, prop->data, &parameter.value))
+        {
+          g_warning ("failed to set property %s.%s to %s",
+                     g_type_name (object_type), prop->name, prop->data);
+          continue;
+        }
+
+      if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+        g_array_append_val (*construct_parameters, parameter);
+      else
+        g_array_append_val (*parameters, parameter);
+    }
+
+  g_type_class_unref (oclass);
+}
+
+static GObject *
+gtk_builder_get_internal_child (GtkBuilder  *builder,
+                                ObjectInfo  *info,
+                                const gchar *childname)
+{
+  GObject *obj = NULL;
+
+  while (!obj)
+    {
+      if (!info->parent)
+        break;
+
+      info = (ObjectInfo*)((ChildInfo*)info->parent)->parent;
+      if (!info)
+        break;
+
+      GTK_NOTE (BUILDER,
+                g_print ("Trying to get internal child %s from %s\n",
+                         childname,
+                         gtk_buildable_get_name (GTK_BUILDABLE (info->object))));
+
+      if (GTK_IS_BUILDABLE (info->object))
+          obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
+                                                  builder,
+                                                  childname);
+    };
+
+  if (!obj)
+    g_error ("Unknown internal child: %s\n", childname);
+
+  return obj;
+}
+
+GObject *
+_gtk_builder_construct (GtkBuilder *builder,
+                        ObjectInfo *info)
+{
+  GArray *parameters, *construct_parameters;
+  GType object_type;
+  GObject *obj;
+  int i;
+  GtkBuildableIface *iface;
+  gboolean custom_set_property;
+  GtkBuildable *buildable;
+
+  g_assert (info->class_name != NULL);
+  object_type = gtk_builder_get_type_from_name (builder, info->class_name);
+  if (object_type == G_TYPE_INVALID)
+    g_error ("Invalid type: %s", info->class_name);
+
+  gtk_builder_get_parameters (builder, object_type,
+                              info->id,
+                              info->properties,
+                              &parameters,
+                              &construct_parameters);
+
+  if (info->constructor)
+    {
+      GObject *constructor;
+
+      constructor = gtk_builder_get_object (builder, info->constructor);
+      if (constructor == NULL)
+        g_error ("Unknown constructor for %s: %s\n", info->id,
+                 info->constructor);
+
+      obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
+                                           builder,
+                                           info->id);
+      g_assert (obj != NULL);
+      if (construct_parameters->len)
+        g_warning ("Can't pass in construct-only parameters to %s", info->id);
+
+    }
+  else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
+    {
+      gchar *childname = ((ChildInfo*)info->parent)->internal_child;
+      obj = gtk_builder_get_internal_child (builder, info, childname);
+      if (construct_parameters->len)
+        g_warning ("Can't pass in construct-only parameters to %s", childname);
+    }
+  else
+    {
+      obj = g_object_newv (object_type,
+                           construct_parameters->len,
+                           (GParameter *)construct_parameters->data);
+
+      GTK_NOTE (BUILDER,
+                g_print ("created %s of type %s\n", info->id, info->class_name));
+
+      for (i = 0; i < construct_parameters->len; i++)
+        {
+          GParameter *param = &g_array_index (construct_parameters,
+                                              GParameter, i);
+          g_value_unset (&param->value);
+        }
+    }
+  g_array_free (construct_parameters, TRUE);
+
+  custom_set_property = FALSE;
+  buildable = NULL;
+  iface = NULL;
+  if (GTK_IS_BUILDABLE (obj))
+    {
+      buildable = GTK_BUILDABLE (obj);
+      iface = GTK_BUILDABLE_GET_IFACE (obj);
+      if (iface->set_property)
+        custom_set_property = TRUE;
+    }
+
+  for (i = 0; i < parameters->len; i++)
+    {
+      GParameter *param = &g_array_index (parameters, GParameter, i);
+      if (custom_set_property)
+        iface->set_property (buildable, builder, param->name, &param->value);
+      else
+        g_object_set_property (obj, param->name, &param->value);
+
+#if G_ENABLE_DEBUG
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+        {
+          gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
+          g_print ("set %s: %s = %s\n", info->id, param->name, str);
+          g_free (str);
+        }
+#endif      
+      g_value_unset (&param->value);
+    }
+  g_array_free (parameters, TRUE);
+  
+  if (GTK_IS_BUILDABLE (obj))
+    gtk_buildable_set_name (buildable, info->id);
+  else
+    g_object_set_data_full (obj,
+                            "gtk-builder-name",
+                            g_strdup (info->id),
+                            g_free);
+
+  if (!info->parent)
+    {
+      g_free (builder->priv->current_toplevel);
+      builder->priv->current_toplevel = g_strdup (info->id);
+    }
+  g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
+  
+  builder->priv->signals = g_slist_concat (builder->priv->signals,
+                                           g_slist_copy (info->signals));
+  return obj;
+}
+
+
+void
+_gtk_builder_add (GtkBuilder *builder,
+                  ChildInfo  *child_info)
+{
+  GObject *object;
+  GObject *parent;
+
+  /* Internal children are already added
+   * Also prevent us from being called twice.
+   */
+  if (!child_info ||
+      child_info->internal_child ||
+      child_info->added)
+    return;
+
+  object = child_info->object;
+  if (!object)
+    return;
+
+  if (!child_info->parent)
+    {
+      g_warning ("%s: Not adding, No parent\n",
+                 gtk_buildable_get_name (GTK_BUILDABLE (object)));
+      return;
+    }
+
+  g_assert (object != NULL);
+
+  parent = ((ObjectInfo*)child_info->parent)->object;
+  g_assert (GTK_IS_BUILDABLE (parent));
+
+  GTK_NOTE (BUILDER,
+            g_print ("adding %s to %s\n",
+                     gtk_buildable_get_name (GTK_BUILDABLE (object)),
+                     gtk_buildable_get_name (GTK_BUILDABLE (parent))));
+  
+  gtk_buildable_add (GTK_BUILDABLE (parent), builder, object,
+                     child_info->type);
+
+  child_info->added = TRUE;
+}
+
+static void
+apply_delayed_properties (const gchar *window_name,
+                          GSList      *props,
+                          GtkBuilder  *builder)
+{
+  GSList *l;
+  DelayedProperty *property;
+  GObject *object;
+  GType object_type;
+  GObjectClass *oclass;
+  GParamSpec *pspec;
+
+  g_assert (props != NULL);
+  props = g_slist_reverse (props);
+  for (l = props; l; l = l->next)
+    {
+      property = (DelayedProperty*)l->data;
+      object = g_hash_table_lookup (builder->priv->objects, property->object);
+      g_assert (object != NULL);
+
+      object_type = G_OBJECT_TYPE (object);
+      g_assert (object_type != G_TYPE_INVALID);
+
+      oclass = g_type_class_ref (object_type);
+      g_assert (oclass != NULL);
+
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
+                                            property->name);
+      if (!pspec)
+        g_warning ("Unknown property: %s.%s\n", g_type_name (object_type),
+                   property->name);
+      else
+        {
+          GObject *obj;
+
+          obj = g_hash_table_lookup (builder->priv->objects, property->value);
+          if (!obj)
+            g_warning ("No object called: %s\n", property->object);
+          else
+            g_object_set (object, property->name, obj, NULL);
+        }
+      g_free (property->value);
+      g_free (property->object);
+      g_free (property->name);
+      g_slice_free (DelayedProperty, property);
+      g_type_class_unref (oclass);
+    }
+  g_slist_free (props);
+}
+
+void
+_gtk_builder_finish (GtkBuilder  *builder)
+{
+  if (builder->priv->delayed_properties)
+    g_hash_table_foreach (builder->priv->delayed_properties,
+                          (GHFunc)apply_delayed_properties, builder);
+}
+
+/**
+ * gtk_builder_new:
+ *
+ * Creates a new builder object.
+ *
+ * Return value: a new builder object.
+ *
+ * Since: 2.12
+ **/
+GtkBuilder *
+gtk_builder_new (void)
+{
+  return g_object_new (GTK_TYPE_BUILDER, NULL);
+}
+
+/**
+ * gtk_builder_add_from_file:
+ * @builder: a #GtkBuilder
+ * @filename: the name of the file to parse
+ * @error: return location for an error
+ *
+ * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and 
+ * merges it with the current contents of @builder. 
+ * 
+ * Returns: A positive value on success, 0 if an error occurred
+ *
+ * Since: 2.12
+ **/
+guint
+gtk_builder_add_from_file (GtkBuilder   *builder,
+                           const gchar  *filename,
+                           GError      **error)
+{
+  char *buffer;
+  unsigned length;
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (filename != NULL, 0);
+
+  tmp_error = NULL;
+
+  if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+  
+  _gtk_builder_parser_parse_buffer (builder, filename,
+                                    buffer, length,
+                                    &tmp_error);
+
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  g_free (buffer);
+
+  return 1;
+}
+
+/**
+ * gtk_builder_add_from_string:
+ * @builder: a #GtkBuilder
+ * @buffer: the string to parse
+ * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
+ * @error: return location for an error
+ *
+ * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and 
+ * merges it with the current contents of @builder. 
+ * 
+ * Returns: A positive value on success, 0 if an error occurred
+ *
+ * Since: 2.12
+ **/
+guint
+gtk_builder_add_from_string (GtkBuilder   *builder,
+                             const gchar  *buffer,
+                             gsize         length,
+                             GError      **error)
+{
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  tmp_error = NULL;
+
+  _gtk_builder_parser_parse_buffer (builder, "<input>",
+                                    buffer, length,
+                                    &tmp_error);
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  return 1;
+}
+
+/**
+ * gtk_builder_get_object:
+ * @builder: a #GtkBuilder
+ * @name: name of object to get
+ *
+ * Return value: GObject or %NULL if it could not be found in the object tree.
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_builder_get_object (GtkBuilder  *builder,
+                        const gchar *name)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  return g_hash_table_lookup (builder->priv->objects, name);
+}
+
+static void
+object_add_to_list (gchar *object_id,
+                    GObject *object,
+                    GSList **list)
+{
+  *list = g_slist_prepend (*list, object);
+}
+
+/**
+ * gtk_builder_get_objects:
+ * @builder: a #GtkBuilder
+ *
+ * Return value: a newly-allocated #GSList containing all the objects
+ *   constructed by GtkBuilder instance.
+ *
+ * Since: 2.12
+ **/
+GSList *
+gtk_builder_get_objects (GtkBuilder *builder)
+{
+  GSList *objects = NULL;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  g_hash_table_foreach (builder->priv->objects, (GHFunc)object_add_to_list, &objects);
+
+  return g_slist_reverse (objects);
+}
+
+/**
+ * gtk_builder_set_translation_domain:
+ * @builder: a #GtkBuilder
+ * @domain: the translation domain or %NULL
+ *
+ * Sets the translation domain and uses dgettext() for translating the
+ * property values marked as translatable from an interface description.
+ * You can also pass in %NULL to this method to use gettext() instead of
+ * dgettext().
+ *
+ * Since: 2.12
+ **/
+void
+gtk_builder_set_translation_domain (GtkBuilder  *builder,
+                                    const gchar *domain)
+{
+  gchar *new_domain;
+    
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  new_domain = g_strdup (domain);
+  g_free (builder->priv->domain);
+  builder->priv->domain = new_domain;
+
+  g_object_notify (G_OBJECT (builder), "translation-domain");
+}
+
+/**
+ * gtk_builder_get_translation_domain:
+ * @builder: a #GtkBuilder
+ *
+ * Return value : the translation domain. This string is owned
+ * by the builder object and must not be modified or freed.
+ *
+ * Since: 2.12
+ **/
+const gchar *
+gtk_builder_get_translation_domain (GtkBuilder *builder)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  return builder->priv->domain;
+}
+
+typedef struct {
+  GModule *module;
+  gpointer data;
+} connect_args;
+
+static void
+gtk_builder_connect_signals_default (GtkBuilder    *builder,
+                                    GObject       *object,
+                                    const gchar   *signal_name,
+                                    const gchar   *handler_name,
+                                    GObject       *connect_object,
+                                    GConnectFlags  flags,
+                                    gpointer       user_data)
+{
+  GCallback func;
+  connect_args *args = (connect_args*)user_data;
+  
+  if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
+    {
+      g_warning ("could not find signal handler '%s'", handler_name);
+      return;
+    }
+
+  if (connect_object)
+    g_signal_connect_object (object, signal_name, func, connect_object, flags);
+  else
+    g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
+}
+
+
+/**
+ * gtk_builder_connect_signals:
+ * @builder: a #GtkBuilder
+ * @user_data: a pointer to a structure sent in as user data to all signals
+ *
+ * This method is a simpler variation of gtk_builder_connect_signals_full().
+ * It uses #GModule's introspective features (by opening the module %NULL) to
+ * look at the application's symbol table.  From here it tries to match
+ * the signal handler names given in the interface description with
+ * symbols in the application and connects the signals.
+ * 
+ * Note that this function will not work correctly if #GModule is not
+ * supported on the platform.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_builder_connect_signals (GtkBuilder *builder,
+                            gpointer    user_data)
+{
+  connect_args *args;
+  
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  
+  if (!g_module_supported ())
+    g_error ("gtk_builder_connect_signals requires working GModule");
+
+  args = g_slice_new0 (connect_args);
+  args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+  args->data = user_data;
+  
+  gtk_builder_connect_signals_full (builder,
+                                    gtk_builder_connect_signals_default,
+                                    args);
+  g_module_close (args->module);
+
+  g_slice_free (connect_args, args);
+}
+
+/**
+ * GtkBuilderConnectFunc:
+ * @builder: a #GtkBuilder
+ * @object: a GObject subclass to connect a signal to
+ * @signal_name: name of the signal
+ * @handler_name: name of the handler
+ * @connect_object: GObject, if non-%NULL, use g_signal_connect_object.
+ * @flags: #GConnectFlags to use
+ * @user_data: user data
+ *
+ * This is the signature of a function used to connect signals.  It is used
+ * by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
+ * methods.  It is mainly intended for interpreted language bindings, but
+ * could be useful where the programmer wants more control over the signal
+ * connection process.
+ *
+ * Since: 2.12
+ */
+
+/**
+ * gtk_builder_connect_signals_full:
+ * @builder: a #GtkBuilder
+ * @func: the function used to connect the signals.
+ * @user_data: arbitrary data that will be passed to the connection function.
+ *
+ * This function can be thought of the interpreted language binding
+ * version of gtk_builder_signal_autoconnect(), except that it does not
+ * require gmodule to function correctly.
+ *
+ * Since: 2.12
+ */
+void
+gtk_builder_connect_signals_full (GtkBuilder            *builder,
+                                  GtkBuilderConnectFunc  func,
+                                  gpointer               user_data)
+{
+  GSList *l;
+  GObject *object;
+  GObject *connect_object;
+  
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (func != NULL);
+  
+  if (!builder->priv->signals)
+    return;
+
+  builder->priv->signals = g_slist_reverse (builder->priv->signals);
+  for (l = builder->priv->signals; l; l = l->next)
+    {
+      SignalInfo *signal = (SignalInfo*)l->data;
+
+      g_assert (signal != NULL);
+      g_assert (signal->name != NULL);
+
+      object = g_hash_table_lookup (builder->priv->objects,
+                                   signal->object_name);
+      g_assert (object != NULL);
+
+      connect_object = NULL;
+      
+      if (signal->connect_object_name)
+       {
+         connect_object = g_hash_table_lookup (builder->priv->objects,
+                                               signal->connect_object_name);
+         if (!connect_object)
+             g_warning ("could not lookup object %s on signal %s of object %s",
+                        signal->connect_object_name, signal->name,
+                        signal->object_name);
+       }
+                                                 
+      func (builder, object, signal->name, signal->handler, 
+           connect_object, signal->flags, user_data);
+    }
+
+  g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (builder->priv->signals);
+  builder->priv->signals = NULL;
+}
+
+/**
+ * gtk_builder_value_from_string
+ * @pspec: the GParamSpec for the property
+ * @string: the string representation of the value.
+ * @value: the GValue to store the result in.
+ *
+ * This function demarshals a value from a string.  This function
+ * calls g_value_init() on the @value argument, so it need not be
+ * initialised beforehand.
+ *
+ * This function can handle char, uchar, boolean, int, uint, long,
+ * ulong, enum, flags, float, double, string, GdkColor and
+ * GtkAdjustment type values.  Support for GtkWidget type values is
+ * still to come.
+ *
+ * Returns: %TRUE on success.
+ *
+ * Since: 2.12
+ */
+gboolean
+gtk_builder_value_from_string (GParamSpec  *pspec,
+                               const gchar *string,
+                               GValue      *value)
+{
+  /*
+   * GParamSpecUnichar has the internal type G_TYPE_UINT,
+   * so we cannot handle this in the switch, do it separately
+   */
+  if (G_IS_PARAM_SPEC_UNICHAR (pspec))
+    {
+      gunichar c;
+      g_value_init (value, G_TYPE_UINT);
+      c = g_utf8_get_char_validated (string, strlen (string));
+      if (c > 0)
+        g_value_set_uint (value, c);
+      return TRUE;
+    }
+
+  return gtk_builder_value_from_string_type (G_PARAM_SPEC_VALUE_TYPE (pspec),
+                                             string, value);
+}
+
+/**
+ * gtk_builder_value_from_string_type
+ * @type: the GType of the value
+ * @string: the string representation of the value.
+ * @value: the GValue to store the result in.
+ *
+ * Like gtk_builder_value_from_string(), but takes a #GType instead of #GParamSpec.
+ *
+ * Returns: %TRUE on success.
+ *
+ * Since: 2.12
+ */
+gboolean
+gtk_builder_value_from_string_type (GType        type,
+                                    const gchar *string,
+                                    GValue      *value)
+{
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  g_value_init (value, type);
+
+  switch (G_TYPE_FUNDAMENTAL (type))
+    {
+    case G_TYPE_CHAR:
+      g_value_set_char (value, string[0]);
+      break;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (value, (guchar)string[0]);
+      break;
+    case G_TYPE_BOOLEAN:
+      {
+        gboolean b;
+
+        if (g_ascii_tolower (string[0]) == 't')
+          b = TRUE;
+        else if (g_ascii_tolower (string[0]) == 'y')
+          b = FALSE;
+        else {
+          errno = 0;
+          b = strtol (string, NULL, 0);
+          if (errno) {
+            g_warning ("could not parse int `%s'", string);
+            break;
+          }
+        }
+        g_value_set_boolean (value, b);
+        break;
+      }
+    case G_TYPE_INT:
+    case G_TYPE_LONG:
+      {
+        long l;
+        errno = 0;
+        l = strtol (string, NULL, 0);
+        if (errno) {
+          g_warning ("could not parse long `%s'", string);
+          break;
+        }
+        if (G_VALUE_HOLDS_INT (value))
+          g_value_set_int (value, l);
+        else
+          g_value_set_long (value, l);
+        break;
+      }
+    case G_TYPE_UINT:
+    case G_TYPE_ULONG:
+      {
+        ulong ul;
+        errno = 0;
+        ul = strtoul (string, NULL, 0);
+        if (errno)
+          {
+            g_warning ("could not parse ulong `%s'", string);
+            break;
+          }
+        if (G_VALUE_HOLDS_UINT (value))
+          g_value_set_uint (value, strtoul (string, NULL, 0));
+        else 
+          g_value_set_ulong (value, strtoul (string, NULL, 0));
+        break;
+      }
+    case G_TYPE_ENUM:
+      g_value_set_enum (value, _gtk_builder_enum_from_string (type, string));
+      break;
+    case G_TYPE_FLAGS:
+      g_value_set_flags (value, _gtk_builder_flags_from_string (type, string));
+      break;
+    case G_TYPE_FLOAT:
+    case G_TYPE_DOUBLE:
+      {
+        double d;
+        errno = 0;
+        d = g_ascii_strtod (string, NULL);
+        if (errno)
+          {
+            g_warning ("could not parse double `%s'", string);
+            break;
+          }
+        if (G_VALUE_HOLDS_FLOAT (value))
+          g_value_set_float (value, d);
+        else
+          g_value_set_double (value, d);
+        break;
+      }
+    case G_TYPE_STRING:
+      g_value_set_string (value, string);
+      break;
+    case G_TYPE_BOXED:
+      if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
+        {
+          GdkColor colour = { 0, };
+
+          if (gdk_color_parse (string, &colour) &&
+              gdk_colormap_alloc_color (gtk_widget_get_default_colormap (),
+                                        &colour, FALSE, TRUE))
+            g_value_set_boxed (value, &colour);
+          else
+            {
+              g_warning ("could not parse colour name `%s'", string);
+              ret = FALSE;
+            }
+        }
+      else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        {
+          char **vector = g_strsplit (string, "\n", 0);
+          g_value_take_boxed (value, vector);
+        }
+      else
+        ret = FALSE;
+      break;
+    case G_TYPE_OBJECT:
+#if 0
+        if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+      {
+        gchar *filename;
+        GError *error = NULL;
+        GdkPixbuf *pixbuf;
+
+        filename = gtk_xml_relative_file (xml, string);
+        pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+        if (pixbuf)
+          {
+            g_value_set_object (value, pixbuf);
+            g_object_unref (G_OBJECT (pixbuf));
+          }
+        else
+          {
+            g_warning ("Error loading image: %s", error->message);
+            g_error_free (error);
+            ret = FALSE;
+          }
+        g_free (filename);
+      }
+        else
+#endif
+          ret = FALSE;
+      break;
+    default:
+      ret = FALSE;
+      break;
+    }
+
+  return ret;
+}
+
+static gint
+_gtk_builder_enum_from_string (GType type, const char *string)
+{
+  GEnumClass *eclass;
+  GEnumValue *ev;
+  gchar *endptr;
+  gint ret = 0;
+
+  g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
+  g_return_val_if_fail (string != NULL, 0);
+  
+  ret = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  eclass = g_type_class_ref (type);
+  ev = g_enum_get_value_by_name (eclass, string);
+  if (!ev)
+    ev = g_enum_get_value_by_nick (eclass, string);
+
+  if (ev)
+    ret = ev->value;
+
+  g_type_class_unref (eclass);
+
+  return ret;
+}
+
+guint
+_gtk_builder_flags_from_string (GType type, const char *string)
+{
+  GFlagsClass *fclass;
+  gchar *endptr, *prevptr;
+  guint i, j, ret;
+  char *flagstr;
+  GFlagsValue *fv;
+  const char  *flag;
+  gunichar ch;
+  gboolean eos;
+
+  g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
+  g_return_val_if_fail (string != 0, 0);
+
+  ret = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  fclass = g_type_class_ref (type);
+
+  flagstr = g_strdup (string);
+  for (ret = i = j = 0; ; i++)
+    {
+
+      eos = flagstr[i] == '\0';
+
+      if (!eos && flagstr[i] != '|')
+        continue;
+
+      flag = &flagstr[j];
+      endptr = &flagstr[i];
+
+      if (!eos)
+        {
+          flagstr[i++] = '\0';
+          j = i;
+        }
+
+      /* trim spaces */
+      for (;;)
+        {
+          ch = g_utf8_get_char (flag);
+          if (!g_unichar_isspace (ch))
+            break;
+          flag = g_utf8_next_char (flag);
+        }
+
+      while (endptr > flag)
+        {
+          prevptr = g_utf8_prev_char (endptr);
+          ch = g_utf8_get_char (prevptr);
+          if (!g_unichar_isspace (ch))
+            break;
+          endptr = prevptr;
+        }
+
+      if (endptr > flag)
+        {
+          *endptr = '\0';
+          fv = g_flags_get_value_by_name (fclass, flag);
+
+          if (!fv)
+            fv = g_flags_get_value_by_nick (fclass, flag);
+
+          if (fv)
+            ret |= fv->value;
+          else
+            g_warning ("Unknown flag: '%s'", flag);
+        }
+
+      if (eos)
+        break;
+    }
+
+  g_free (flagstr);
+
+  g_type_class_unref (fclass);
+
+  return ret;
+}
+
+/**
+ * gtk_builder_get_type_from_name:
+ * @builder: a #GtkBuilder
+ * @typename: Type name to lookup.
+ *
+ * This method is used to lookup a type. It can be implemented in a subclass to
+ * override the #GType of an object created by the builder.
+ *
+ * Since 2.12
+ */
+GType
+gtk_builder_get_type_from_name (GtkBuilder *builder, const gchar *typename)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
+  g_return_val_if_fail (typename != NULL, G_TYPE_INVALID);
+
+  return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, typename);
+}
+
+/**
+ * gtk_builder_error_quark:
+ *
+ * Registers an error quark for #GtkBuilder if necessary.
+ * 
+ * Return value: The error quark used for #GtkBuilder errors.
+ *
+ * Since: 2.12
+ **/
+GQuark
+gtk_builder_error_quark (void)
+{
+  return g_quark_from_static_string ("gtk-builder-error-quark");
+}
+
+
+#define __GTK_BUILDER_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h
new file mode 100644 (file)
index 0000000..81ea9a7
--- /dev/null
@@ -0,0 +1,122 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_BUILDER_H__
+#define __GTK_BUILDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDER                 (gtk_builder_get_type ())
+#define GTK_BUILDER(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDER, GtkBuilder))
+#define GTK_BUILDER_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_BUILDER, GtkBuilderClass))
+#define GTK_IS_BUILDER(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDER))
+#define GTK_IS_BUILDER_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_BUILDER))
+#define GTK_BUILDER_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_BUILDER, GtkBuilderClass))
+
+#define GTK_BUILDER_ERROR                (gtk_builder_error_quark ())
+
+typedef struct _GtkBuilder        GtkBuilder;
+typedef struct _GtkBuilderClass   GtkBuilderClass;
+typedef struct _GtkBuilderPrivate GtkBuilderPrivate;
+
+typedef enum
+{
+  GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION,
+  GTK_BUILDER_ERROR_UNHANDLED_TAG,
+  GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
+  GTK_BUILDER_ERROR_INVALID_ATTRIBUTE,
+  GTK_BUILDER_ERROR_INVALID_TAG
+} GtkBuilderError;
+
+GQuark gtk_builder_error_quark (void);
+
+struct _GtkBuilder
+{
+  GObject parent_instance;
+
+  GtkBuilderPrivate *priv;
+};
+
+struct _GtkBuilderClass
+{
+  GObjectClass parent_class;
+  
+  GType (* get_type_from_name) (GtkBuilder *builder,
+                                const char *typename);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+  void (*_gtk_reserved6) (void);
+  void (*_gtk_reserved7) (void);
+  void (*_gtk_reserved8) (void);
+};
+
+typedef void (*GtkBuilderConnectFunc) (GtkBuilder    *builder,
+                                      GObject       *object,
+                                      const gchar   *signal_name,
+                                      const gchar   *handler_name,
+                                      GObject       *connect_object,
+                                      GConnectFlags  flags,
+                                      gpointer       user_data);
+
+GType        gtk_builder_get_type                (void) G_GNUC_CONST;
+GtkBuilder*  gtk_builder_new                     (void);
+
+guint        gtk_builder_add_from_file           (GtkBuilder    *builder,
+                                                  const gchar   *filename,
+                                                  GError       **error);
+guint        gtk_builder_add_from_string         (GtkBuilder    *builder,
+                                                  const gchar   *buffer,
+                                                  gsize          length,
+                                                  GError       **error);
+GObject*     gtk_builder_get_object              (GtkBuilder    *builder,
+                                                  const gchar   *name);
+GSList*      gtk_builder_get_objects             (GtkBuilder    *builder);
+void         gtk_builder_connect_signals         (GtkBuilder    *builder,
+                                                 gpointer       user_data);
+void         gtk_builder_connect_signals_full    (GtkBuilder    *builder,
+                                                  GtkBuilderConnectFunc func,
+                                                 gpointer       user_data);
+void         gtk_builder_set_translation_domain  (GtkBuilder           *builder,
+                                                  const gchar          *domain);
+const gchar* gtk_builder_get_translation_domain  (GtkBuilder           *builder);
+GType        gtk_builder_get_type_from_name      (GtkBuilder           *builder,
+                                                  const char           *typename);
+
+gboolean     gtk_builder_value_from_string       (GParamSpec           *pspec,
+                                                  const gchar          *string,
+                                                  GValue               *value);
+gboolean     gtk_builder_value_from_string_type  (GType                 type,
+                                                  const gchar          *string,
+                                                  GValue               *value);
+guint        _gtk_builder_flags_from_string      (GType         type,
+                                                 const char    *string);
+
+#define GTK_BUILDER_WARN_INVALID_CHILD_TYPE(object, type) \
+  g_warning ("'%s' is not a valid child type of '%s'", type, g_type_name (G_OBJECT_TYPE (type)))
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDER_H__ */
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
new file mode 100644 (file)
index 0000000..6d82b35
--- /dev/null
@@ -0,0 +1,851 @@
+/* gtkbuilderparser.c
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gfileutils.h>
+#include <glib/gi18n.h>
+#include <glib/gmacros.h>
+#include <glib/gmessages.h>
+#include <glib/gslist.h>
+#include <glib/gstrfuncs.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <gdk/gdkenumtypes.h>
+#include <gdk/gdkkeys.h>
+#include <gtk/gtktypeutils.h>
+#include "gtkbuilderprivate.h"
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkdebug.h"
+#include "gtktypeutils.h"
+#include "gtkalias.h"
+
+static void free_property_info (PropertyInfo *info,
+                                gpointer      user_data);
+
+static inline void
+state_push (ParserData *data, gpointer info)
+{
+  data->stack = g_slist_prepend (data->stack, info);
+}
+
+static inline gpointer
+state_peek (ParserData *data)
+{
+  if (!data->stack)
+    return NULL;
+
+  return data->stack->data;
+}
+
+static inline gpointer
+state_pop (ParserData *data)
+{
+  gpointer old = NULL;
+
+  if (!data->stack)
+    return NULL;
+
+  old = data->stack->data;
+  data->stack = g_slist_delete_link (data->stack, data->stack);
+  return old;
+}
+#define state_peek_info(data, st) ((st*)state_peek(data))
+#define state_pop_info(data, st) ((st*)state_pop(data))
+
+static void
+error_missing_attribute (ParserData *data,
+                         const gchar *tag,
+                         const gchar *attribute,
+                         GError **error)
+{
+  gint line_number, char_number;
+
+  g_markup_parse_context_get_position (data->ctx,
+                                       &line_number,
+                                       &char_number);
+
+  g_set_error (error,
+               GTK_BUILDER_ERROR,
+               GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
+               "%s:%d:%d <%s> requires attribute \"%s\"",
+               data->filename,
+               line_number, char_number, tag, attribute);
+}
+
+static void
+error_invalid_attribute (ParserData *data,
+                         const gchar *tag,
+                         const gchar *attribute,
+                         GError **error)
+{
+  gint line_number, char_number;
+
+  g_markup_parse_context_get_position (data->ctx,
+                                       &line_number,
+                                       &char_number);
+
+  g_set_error (error,
+               GTK_BUILDER_ERROR,
+               GTK_BUILDER_ERROR_INVALID_ATTRIBUTE,
+               "%s:%d:%d '%s' is not a valid attribute of <%s>",
+               data->filename,
+               line_number, char_number, attribute, tag);
+}
+
+static void
+error_invalid_tag (ParserData *data,
+                  const gchar *tag,
+                  const gchar *expected,
+                  GError **error)
+{
+  gint line_number, char_number;
+
+  g_markup_parse_context_get_position (data->ctx,
+                                       &line_number,
+                                       &char_number);
+
+  if (expected)
+    g_set_error (error,
+                GTK_BUILDER_ERROR,
+                GTK_BUILDER_ERROR_INVALID_TAG,
+                "%s:%d:%d '%s' is not a valid tag here, expected a '%s' tag",
+                data->filename,
+                line_number, char_number, tag, expected);
+  else
+    g_set_error (error,
+                GTK_BUILDER_ERROR,
+                GTK_BUILDER_ERROR_INVALID_TAG,
+                "%s:%d:%d '%s' is not a valid tag here",
+                data->filename,
+                line_number, char_number, tag);
+}
+
+static GObject *
+builder_construct (ParserData *data,
+                   ObjectInfo *object_info)
+{
+  GObject *object;
+
+  g_assert (object_info != NULL);
+
+  if (object_info->object)
+    return object_info->object;
+
+  object_info->properties = g_slist_reverse (object_info->properties);
+
+  object = _gtk_builder_construct (data->builder, object_info);
+  g_assert (G_IS_OBJECT (object));
+
+  object_info->object = object;
+
+  return object;
+}
+
+static void
+parse_object (ParserData   *data,
+              const gchar  *element_name,
+              const gchar **names,
+              const gchar **values,
+              GError      **error)
+{
+  ObjectInfo *object_info;
+  ChildInfo* child_info;
+  int i;
+  gchar *object_class = NULL;
+  gchar *object_id = NULL;
+  gchar *constructor = NULL;
+
+  child_info = state_peek_info (data, ChildInfo);
+  if (child_info && strcmp (child_info->tag.name, "object") == 0)
+    {
+      error_invalid_tag (data, element_name, NULL, error);
+      return;
+    }
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "class") == 0)
+        object_class = g_strdup (values[i]);
+      else if (strcmp (names[i], "id") == 0)
+        object_id = g_strdup (values[i]);
+      else if (strcmp (names[i], "constructor") == 0)
+        constructor = g_strdup (values[i]);
+      else
+       {
+         error_invalid_attribute (data, element_name, values[i], error);
+         return;
+       }
+    }
+
+  if (!object_class)
+    {
+      error_missing_attribute (data, element_name, "class", error);
+      return;
+    }
+
+  if (!object_id)
+    {
+      error_missing_attribute (data, element_name, "id", error);
+      return;
+    }
+
+  object_info = g_slice_new0 (ObjectInfo);
+  object_info->class_name = object_class;
+  object_info->id = object_id;
+  object_info->constructor = constructor;
+  state_push (data, object_info);
+  g_assert (state_peek (data) != NULL);
+  object_info->tag.name = element_name;
+
+  if (child_info)
+    object_info->parent = (CommonInfo*)child_info;
+}
+
+static void
+free_object_info (ObjectInfo *info)
+{
+  /* Do not free the signal items, which GtkBuilder takes ownership of */
+  g_slist_free (info->signals);
+  g_slist_foreach (info->properties,
+                   (GFunc)free_property_info, NULL);
+  g_slist_free (info->properties);
+  g_free (info->constructor);
+  g_free (info->class_name);
+  g_free (info->id);
+  g_slice_free (ObjectInfo, info);
+}
+
+static gchar *
+_get_type_by_symbol (const gchar* symbol)
+{
+  static GModule *module = NULL;
+  GTypeGetFunc func;
+  GType type;
+  
+  if (!module)
+    module = g_module_open (NULL, 0);
+
+  if (!g_module_symbol (module, symbol, (gpointer)&func))
+    return NULL;
+  
+  type = func ();
+  if (type == G_TYPE_INVALID)
+    return NULL;
+
+  return g_strdup (g_type_name (type));
+}
+
+static void
+parse_child (ParserData   *data,
+             const gchar  *element_name,
+             const gchar **names,
+             const gchar **values,
+             GError      **error)
+
+{
+  ObjectInfo* object_info;
+  ChildInfo *child_info;
+  guint i;
+
+  object_info = state_peek_info (data, ObjectInfo);
+  if (!object_info || strcmp (object_info->tag.name, "object") != 0)
+    {
+      error_invalid_tag (data, element_name, "object", error);
+      return;
+    }
+  
+  child_info = g_slice_new0 (ChildInfo);
+  state_push (data, child_info);
+  g_assert (state_peek (data) != NULL);
+  child_info->tag.name = element_name;
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "type") == 0)
+        child_info->type = g_strdup (values[i]);
+      else if (strcmp (names[i], "internal-child") == 0)
+        child_info->internal_child = g_strdup (values[i]);
+      else if (strcmp (names[i], "type-func") == 0)
+        {
+          child_info->type = _get_type_by_symbol (values[i]);
+          if (!child_info->type)
+            {
+              g_set_error (error, GTK_BUILDER_ERROR, 
+                           GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION,
+                           _("Invalid type function: `%s'"),
+                           values[i]);
+              return;
+            }
+        }
+      else
+       error_invalid_attribute (data, element_name, values[i], error);
+    }
+
+  child_info->parent = (CommonInfo*)object_info;
+
+  object_info->object = builder_construct (data, object_info);
+}
+
+static void
+free_child_info (ChildInfo *info)
+{
+  g_free (info->type);
+  g_free (info->internal_child);
+  g_slice_free (ChildInfo, info);
+}
+
+static void
+parse_property (ParserData   *data,
+                const gchar  *element_name,
+                const gchar **names,
+                const gchar **values,
+                GError      **error)
+{
+  PropertyInfo *info;
+  gchar *name = NULL;
+  gboolean translatable = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "name") == 0)
+        name = g_strdelimit (g_strdup (values[i]), "_", '-');
+      else if (strcmp (names[i], "translatable") == 0)
+        translatable = strcmp (values[i], "yes") == 0;
+      else
+       {
+         error_invalid_attribute (data, element_name, values[i], error);
+         return;
+       }
+    }
+
+  if (!name)
+    {
+      error_missing_attribute (data, element_name, "name", error);
+      return;
+    }
+
+  info = g_slice_new0 (PropertyInfo);
+  info->name = name;
+  info->translatable = translatable;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+static void
+free_property_info (PropertyInfo *info,
+                    gpointer user_data)
+{
+  g_free (info->data);
+  g_free (info->name);
+  g_slice_free (PropertyInfo, info);
+}
+
+static void
+parse_signal (ParserData   *data,
+              const gchar  *element_name,
+              const gchar **names,
+              const gchar **values,
+              GError      **error)
+{
+  SignalInfo *info;
+  gchar *name = NULL;
+  gchar *handler = NULL;
+  gchar *object = NULL;
+  gboolean after = FALSE;
+  gboolean swapped = FALSE;
+  gboolean swapped_set = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "name") == 0)
+        name = g_strdup (values[i]);
+      else if (strcmp (names[i], "handler") == 0)
+        handler = g_strdup (values[i]);
+      else if (strcmp (names[i], "after") == 0)
+        after = strcmp (values[i], "yes") == 0;
+      else if (strcmp (names[i], "swapped") == 0)
+       {
+         swapped = strcmp (values[i], "yes") == 0;
+         swapped_set = TRUE;
+       }
+      else if (strcmp (names[i], "object") == 0)
+        object = g_strdup (values[i]);
+      else
+       {
+         error_invalid_attribute (data, element_name, values[i], error);
+         return;
+       }
+    }
+
+  if (!name)
+    {
+      error_missing_attribute (data, element_name, "name", error);
+      return;
+    }
+  else if (!handler)
+    {
+      error_missing_attribute (data, element_name, "handler", error);
+      return;
+    }
+
+  /* Swapped defaults to FALSE except when object is set */
+  if (object && !swapped_set)
+    swapped = TRUE;
+  
+  info = g_slice_new0 (SignalInfo);
+  info->name = name;
+  info->handler = handler;
+  if (after)
+    info->flags |= G_CONNECT_AFTER;
+  if (swapped)
+    info->flags |= G_CONNECT_SWAPPED;
+  info->connect_object_name = object;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+/* Called by GtkBuilder */
+void
+_free_signal_info (SignalInfo *info,
+                   gpointer user_data)
+{
+  g_free (info->name);
+  g_free (info->handler);
+  g_free (info->connect_object_name);
+  g_free (info->object_name);
+  g_slice_free (SignalInfo, info);
+}
+
+static void
+parse_interface (ParserData   *data,
+                const gchar  *element_name,
+                const gchar **names,
+                const gchar **values,
+                GError      **error)
+{
+  int i;
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "domain") == 0 && !data->domain)
+       {
+         data->domain = g_strdup (values[i]);
+         break;
+       }
+      else
+       error_invalid_attribute (data, "interface", values[i], error);
+    }
+}
+
+static SubParser *
+create_subparser (GObject       *object,
+                 GObject       *child,
+                 const gchar   *element_name,
+                 GMarkupParser *parser,
+                 gpointer       user_data)
+{
+  SubParser *subparser;
+
+  subparser = g_slice_new0 (SubParser);
+  subparser->object = object;
+  subparser->child = child;
+  subparser->tagname = g_strdup (element_name);
+  subparser->start = element_name;
+  subparser->parser = g_memdup (parser, sizeof (GMarkupParser));
+  subparser->data = user_data;
+
+  return subparser;
+}
+
+static void
+free_subparser (SubParser *subparser)
+{
+  g_free (subparser->tagname);
+  g_slice_free (SubParser, subparser);
+}
+
+static gboolean
+subparser_start (GMarkupParseContext *context,
+                const gchar         *element_name,
+                const gchar        **names,
+                const gchar        **values,
+                ParserData          *data,
+                GError             **error)
+{
+  SubParser *subparser = data->subparser;
+
+  if (!subparser->start &&
+      strcmp (element_name, subparser->tagname) == 0)
+    subparser->start = element_name;
+
+  if (subparser->start)
+    {
+      if (subparser->parser->start_element)
+       subparser->parser->start_element (context,
+                                         element_name, names, values,
+                                         subparser->data, error);
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+subparser_end (GMarkupParseContext *context,
+              const gchar         *element_name,
+              ParserData          *data,
+              GError             **error)
+{
+  if (data->subparser->parser->end_element)
+    data->subparser->parser->end_element (context, element_name,
+                                         data->subparser->data, error);
+  
+  if (!strcmp (data->subparser->start, element_name) == 0)
+    return;
+    
+  gtk_buildable_custom_tag_end (GTK_BUILDABLE (data->subparser->object),
+                               data->builder,
+                               data->subparser->child,
+                               element_name,
+                               data->subparser->data);
+  g_free (data->subparser->parser);
+      
+  if (GTK_BUILDABLE_GET_IFACE (data->subparser->object)->custom_finished)
+    data->custom_finalizers = g_slist_prepend (data->custom_finalizers,
+                                              data->subparser);
+  else
+    free_subparser (data->subparser);
+  
+  data->subparser = NULL;
+}
+
+static gboolean
+parse_custom (GMarkupParseContext *context,
+             const gchar         *element_name,
+             const gchar        **names,
+             const gchar        **values,
+             ParserData          *data,
+             GError             **error)
+{
+  CommonInfo* parent_info;
+  GMarkupParser parser;
+  gpointer *subparser_data;
+  GObject *object;
+  GObject *child;
+
+  parent_info = state_peek_info (data, CommonInfo);
+  if (!parent_info)
+    return FALSE;
+
+  if (strcmp (parent_info->tag.name, "object") == 0)
+    {
+      ObjectInfo* object_info = (ObjectInfo*)parent_info;
+      if (!object_info->object)
+       object_info->object = _gtk_builder_construct (data->builder,
+                                                     object_info);
+      g_assert (object_info->object);
+      object = object_info->object;
+      child = NULL;
+    }
+  else if (strcmp (parent_info->tag.name, "child") == 0)
+    {
+      ChildInfo* child_info = (ChildInfo*)parent_info;
+      
+      _gtk_builder_add (data->builder, child_info);
+      
+      object = ((ObjectInfo*)child_info->parent)->object;
+      child  = child_info->object;
+    }
+  else
+    return FALSE;
+
+  if (!gtk_buildable_custom_tag_start (GTK_BUILDABLE (object),
+                                      data->builder,
+                                      child,
+                                      element_name,
+                                      &parser,
+                                      (gpointer*)&subparser_data))
+    return FALSE;
+      
+  data->subparser = create_subparser (object, child, element_name,
+                                     &parser, subparser_data);
+  
+  if (parser.start_element)
+    parser.start_element (context,
+                         element_name, names, values,
+                         subparser_data, error);
+  return TRUE;
+}
+
+static void
+start_element (GMarkupParseContext *context,
+               const gchar         *element_name,
+               const gchar        **names,
+               const gchar        **values,
+               gpointer             user_data,
+               GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+
+#ifdef GTK_ENABLE_DEBUG
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    {
+      GString *tags = g_string_new ("");
+      int i;
+      for (i = 0; names[i]; i++)
+        g_string_append_printf (tags, "%s=\"%s\" ", names[i], values[i]);
+
+      if (i)
+        {
+          g_string_insert_c (tags, 0, ' ');
+          g_string_truncate (tags, tags->len - 1);
+        }
+      g_print ("<%s%s>\n", element_name, tags->str);
+      g_string_free (tags, TRUE);
+    }
+#endif
+
+  if (!data->last_element && strcmp (element_name, "interface") != 0)
+    {
+      g_set_error (error, GTK_BUILDER_ERROR, 
+                  GTK_BUILDER_ERROR_UNHANDLED_TAG,
+                  _("Invalid root element: '%s'"),
+                  element_name);
+      return;
+    }
+  data->last_element = element_name;
+
+  if (data->subparser)
+    if (!subparser_start (context, element_name, names, values,
+                         data, error))
+      return;
+  
+  if (strcmp (element_name, "object") == 0)
+    parse_object (data, element_name, names, values, error);
+  else if (strcmp (element_name, "child") == 0)
+    parse_child (data, element_name, names, values, error);
+  else if (strcmp (element_name, "property") == 0)
+    parse_property (data, element_name, names, values, error);
+  else if (strcmp (element_name, "signal") == 0)
+    parse_signal (data, element_name, names, values, error);
+  else if (strcmp (element_name, "interface") == 0)
+    parse_interface (data, element_name, names, values, error);
+  else if (strcmp (element_name, "placeholder") == 0)
+    {
+      /* placeholder has no special treatmeant, but it needs an
+       * if clause to avoid an error below.
+       */
+    }
+  else
+    if (!parse_custom (context, element_name, names, values,
+                      data, error))
+      g_set_error (error, GTK_BUILDER_ERROR, 
+                  GTK_BUILDER_ERROR_UNHANDLED_TAG,
+                  _("Unhandled tag: '%s'"),
+                  element_name);
+}
+
+/* Called for close tags </foo> */
+static void
+end_element (GMarkupParseContext *context,
+             const gchar         *element_name,
+             gpointer             user_data,
+             GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+
+  GTK_NOTE (BUILDER, g_print ("</%s>\n", element_name));
+
+  if (data->subparser && data->subparser->start)
+    {
+      subparser_end (context, element_name, data, error);
+      return;
+    }
+
+  if (strcmp (element_name, "object") == 0)
+    {
+      ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
+      ChildInfo* child_info = state_peek_info (data, ChildInfo);
+
+      object_info->object = builder_construct (data, object_info);
+
+      if (child_info)
+        child_info->object = object_info->object;
+
+      if (GTK_IS_BUILDABLE (object_info->object) &&
+          GTK_BUILDABLE_GET_IFACE (object_info->object)->parser_finished)
+        data->finalizers = g_slist_prepend (data->finalizers, object_info->object);
+      free_object_info (object_info);
+    }
+  else if (strcmp (element_name, "property") == 0)
+    {
+      PropertyInfo *prop_info = state_pop_info (data, PropertyInfo);
+      CommonInfo *info = state_peek_info (data, CommonInfo);
+
+      /* Normal properties */
+      if (strcmp (info->tag.name, "object") == 0)
+        {
+          ObjectInfo *object_info = (ObjectInfo*)info;
+          object_info->properties =
+            g_slist_prepend (object_info->properties, prop_info);
+        }
+      else
+        g_assert_not_reached ();
+    }
+  else if (strcmp (element_name, "child") == 0)
+    {
+      ChildInfo *child_info = state_pop_info (data, ChildInfo);
+
+      _gtk_builder_add (data->builder, child_info);
+
+      free_child_info (child_info);
+    }
+  else if (strcmp (element_name, "signal") == 0)
+    {
+      SignalInfo *signal_info = state_pop_info (data, SignalInfo);
+      ObjectInfo *object_info = (ObjectInfo*)state_peek_info (data, CommonInfo);
+      signal_info->object_name = g_strdup (object_info->id);
+      object_info->signals =
+        g_slist_prepend (object_info->signals, signal_info);
+    }
+  else if (strcmp (element_name, "interface") == 0)
+    {
+    }
+  else if (strcmp (element_name, "placeholder") == 0)
+    {
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+}
+
+/* Called for character data */
+/* text is not nul-terminated */
+static void
+text (GMarkupParseContext *context,
+      const gchar         *text,
+      gsize                text_len,
+      gpointer             user_data,
+      GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+  CommonInfo *info;
+
+  if (data->subparser && data->subparser->start)
+    {
+      if (data->subparser->parser->text)
+        data->subparser->parser->text (context, text, text_len,
+                                       data->subparser->data, error);
+      return;
+    }
+
+  if (!data->stack)
+    return;
+
+  info = state_peek_info (data, CommonInfo);
+  g_assert (info != NULL);
+
+  if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
+    {
+      PropertyInfo *prop_info = (PropertyInfo*)info;
+
+      if (prop_info->translatable && text_len)
+        {
+          if (data->domain)
+            text = dgettext (text, data->domain);
+          else
+            text = gettext (text);
+        }
+      prop_info->data = g_strndup (text, text_len);
+    }
+}
+
+static const GMarkupParser parser = {
+  start_element,
+  end_element,
+  text,
+  NULL,
+  NULL
+};
+
+void
+_gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
+                                  const gchar  *filename,
+                                  const gchar  *buffer,
+                                  gsize         length,
+                                  GError      **error)
+{
+  ParserData *data;
+  GSList *l;
+  
+  data = g_new0 (ParserData, 1);
+  data->builder = builder;
+  data->filename = filename;
+  data->domain = g_strdup (gtk_builder_get_translation_domain (builder));
+
+  data->ctx = g_markup_parse_context_new (
+                  &parser, G_MARKUP_TREAT_CDATA_AS_TEXT, data, NULL);
+
+  if (!g_markup_parse_context_parse (data->ctx, buffer, length, error))
+    goto out;
+  
+  gtk_builder_set_translation_domain (data->builder, data->domain);
+  _gtk_builder_finish (builder);
+
+  /* Custom parser_finished */
+  data->custom_finalizers = g_slist_reverse (data->custom_finalizers);
+  for (l = data->custom_finalizers; l; l = l->next)
+    {
+      SubParser *sub = (SubParser*)l->data;
+      
+      gtk_buildable_custom_finished (GTK_BUILDABLE (sub->object),
+                                     builder,
+                                     sub->child,
+                                     sub->tagname,
+                                     sub->data);
+      free_subparser (sub);
+    }
+  
+  /* Common parser_finished, for all created objects */
+  data->finalizers = g_slist_reverse (data->finalizers);
+  for (l = data->finalizers; l; l = l->next)
+    {
+      GtkBuildable *buildable = (GtkBuildable*)l->data;
+      gtk_buildable_parser_finished (GTK_BUILDABLE (buildable), builder);
+    }
+
+ out:
+  g_markup_parse_context_free (data->ctx);
+
+  g_slist_free (data->stack);
+  g_slist_free (data->custom_finalizers);
+  g_slist_free (data->finalizers);
+  g_free (data->domain);
+  g_free (data);
+}
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
new file mode 100644 (file)
index 0000000..1a65d48
--- /dev/null
@@ -0,0 +1,111 @@
+/* gtkbuilderprivate.h
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDER_PRIVATE_H__
+#define __GTK_BUILDER_PRIVATE_H__
+
+#include <glib/gmarkup.h>
+#include <glib/gslist.h>
+
+#include <glib-object.h>
+#include "gtkbuilder.h"
+
+typedef struct {
+  const gchar *name;
+} TagInfo;
+
+typedef struct {
+  TagInfo tag;
+} CommonInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *class_name;
+  gchar *id;
+  gchar *constructor;
+  GSList *properties;
+  GSList *signals;
+  GObject *object;
+  CommonInfo *parent;
+} ObjectInfo;
+
+typedef struct {
+  TagInfo tag;
+  GSList *packing_properties;
+  GObject *object;
+  CommonInfo *parent;
+  gchar *type;
+  gchar *internal_child;
+  gboolean added;
+} ChildInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *name;
+  gchar *data;
+  gboolean translatable;
+} PropertyInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *object_name;
+  gchar *name;
+  gchar *handler;
+  GConnectFlags flags;
+  gchar *connect_object_name;
+} SignalInfo;
+
+typedef struct {
+  GMarkupParser *parser;
+  gchar *tagname;
+  const gchar *start;
+  gpointer data;
+  GObject *object;
+  GObject *child;
+} SubParser;
+
+typedef struct {
+  const gchar *last_element;
+  GtkBuilder *builder;
+  gchar *domain;
+  GSList *stack;
+  SubParser *subparser;
+  GMarkupParseContext *ctx;
+  const gchar *filename;
+  GSList *finalizers;
+  GSList *custom_finalizers;
+} ParserData;
+
+typedef GType (*GTypeGetFunc) (void);
+
+void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
+                                       const gchar *filename,
+                                       const gchar *buffer,
+                                       gsize length,
+                                       GError **error);
+GObject * _gtk_builder_construct (GtkBuilder *builder,
+                                  ObjectInfo *info);
+void      _gtk_builder_add (GtkBuilder *builder,
+                            ChildInfo *child_info);
+void      _gtk_builder_finish (GtkBuilder *builder);
+void _free_signal_info (SignalInfo *info,
+                        gpointer user_data);
+
+#endif /* __GTK_BUILDER_PRIVATE_H__ */
index 10cf3c426759c673d397d910eb6b0f411f7c4841..89f0a1ab03d762979d5feece5f4d08f0c32a039e 100644 (file)
@@ -17,6 +17,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <string.h>
+#include <stdlib.h>
 #include <config.h>
 #include "gtkcelllayout.h"
 #include "gtkintl.h"
@@ -309,5 +311,115 @@ gtk_cell_layout_get_cells (GtkCellLayout *cell_layout)
   return NULL;
 }
 
+typedef struct {
+  GtkCellLayout   *cell_layout;
+  GtkCellRenderer *renderer;
+  gchar           *attr_name;
+} AttributesSubParserData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer             user_data,
+                         GError             **error)
+{
+  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "attribute") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+       parser_data->attr_name = g_strdup (values[i]);
+  else if (strcmp (element_name, "attributes") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+                        const gchar         *text,
+                        gsize                text_len,
+                        gpointer             user_data,
+                        GError             **error)
+{
+  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
+
+  if (!parser_data->attr_name)
+    return;
+  gtk_cell_layout_add_attribute (parser_data->cell_layout,
+                                parser_data->renderer,
+                                parser_data->attr_name, atoi (text));
+  g_free (parser_data->attr_name);
+  parser_data->attr_name = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+gboolean
+_gtk_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                            GtkBuilder    *builder,
+                                            GObject       *child,
+                                            const gchar   *tagname,
+                                            GMarkupParser *parser,
+                                            gpointer      *data)
+{
+  AttributesSubParserData *parser_data;
+
+  if (!child)
+    return FALSE;
+
+  if (strcmp (tagname, "attributes") == 0)
+    {
+      parser_data = g_slice_new0 (AttributesSubParserData);
+      parser_data->cell_layout = GTK_CELL_LAYOUT (buildable);
+      parser_data->renderer = GTK_CELL_RENDERER (child);
+      parser_data->attr_name = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+void
+_gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
+                                          GtkBuilder   *builder,
+                                          GObject      *child,
+                                          const gchar  *tagname,
+                                          gpointer     *data)
+{
+  AttributesSubParserData *parser_data;
+
+  parser_data = (AttributesSubParserData*)data;
+  g_assert (!parser_data->attr_name);
+  g_slice_free (AttributesSubParserData, parser_data);
+}
+
+void
+_gtk_cell_layout_buildable_add (GtkBuildable      *buildable,
+                               GtkBuilder        *builder,
+                               GObject           *child,
+                               const gchar       *type)
+{
+  GtkCellLayoutIface *iface;
+  
+  g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (child));
+
+  iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
+  g_return_if_fail (iface->pack_end != NULL);
+  iface->pack_end (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);
+}
+
 #define __GTK_CELL_LAYOUT_C__
 #include "gtkaliasdef.c"
index 520f35dbc1af68620cdbc230f7dbc6890004e413..8e2e272cb2fdf46b1f8883c592a909e67368e4c2 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <gtk/gtkcellrenderer.h>
 #include <gtk/gtktreeviewcolumn.h>
+#include <gtk/gtkbuildable.h>
+#include <gtk/gtkbuilder.h>
 
 G_BEGIN_DECLS
 
@@ -97,7 +99,21 @@ void  gtk_cell_layout_clear_attributes   (GtkCellLayout         *cell_layout,
 void  gtk_cell_layout_reorder            (GtkCellLayout         *cell_layout,
                                           GtkCellRenderer       *cell,
                                           gint                   position);
-
+gboolean _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                     GtkBuilder    *builder,
+                                                     GObject       *child,
+                                                     const gchar   *tagname,
+                                                     GMarkupParser *parser,
+                                                     gpointer      *data);
+void _gtk_cell_layout_buildable_custom_tag_end       (GtkBuildable  *buildable,
+                                                     GtkBuilder    *builder,
+                                                     GObject       *child,
+                                                     const gchar   *tagname,
+                                                     gpointer      *data);
+void _gtk_cell_layout_buildable_add                  (GtkBuildable  *buildable,
+                                                     GtkBuilder    *builder,
+                                                     GObject       *child,
+                                                     const gchar   *type);
 
 G_END_DECLS
 
index 1cd3fc7065498f7a15d5216ff6444c35f5b44591..f9d49896adb0a2ea05c645b104abacfea3c8e051 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcellview.h"
 #include "gtkcelllayout.h"
 #include "gtkintl.h"
@@ -26,6 +27,7 @@
 #include "gtkcellrendererpixbuf.h"
 #include "gtkprivate.h"
 #include <gobject/gmarshal.h>
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
@@ -105,6 +107,22 @@ static void       gtk_cell_view_cell_layout_reorder            (GtkCellLayout
                                                                 gint                   position);
 static GList *    gtk_cell_view_cell_layout_get_cells          (GtkCellLayout         *layout);
 
+/* buildable */
+static void       gtk_cell_view_buildable_init                 (GtkBuildableIface     *iface);
+static gboolean   gtk_cell_view_buildable_custom_tag_start     (GtkBuildable         *buildable,
+                                                               GtkBuilder            *builder,
+                                                               GObject               *child,
+                                                               const gchar           *tagname,
+                                                               GMarkupParser         *parser,
+                                                               gpointer              *data);
+static void       gtk_cell_view_buildable_custom_tag_end       (GtkBuildable         *buildable,
+                                                               GtkBuilder            *builder,
+                                                               GObject               *child,
+                                                               const gchar           *tagname,
+                                                               gpointer              *data);
+
+static GtkBuildableIface *parent_buildable_iface;
+
 #define GTK_CELL_VIEW_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_VIEW, GtkCellViewPrivate))
 
 enum
@@ -118,7 +136,9 @@ enum
 
 G_DEFINE_TYPE_WITH_CODE (GtkCellView, gtk_cell_view, GTK_TYPE_WIDGET, 
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-                                               gtk_cell_view_cell_layout_init))
+                                               gtk_cell_view_cell_layout_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_cell_view_buildable_init))
 
 static void
 gtk_cell_view_class_init (GtkCellViewClass *klass)
@@ -174,6 +194,15 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
   g_type_class_add_private (gobject_class, sizeof (GtkCellViewPrivate));
 }
 
+static void
+gtk_cell_view_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_cell_view_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_cell_view_buildable_custom_tag_end;
+}
+
 static void
 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
@@ -1068,5 +1097,37 @@ gtk_cell_view_cell_layout_get_cells (GtkCellLayout *layout)
 }
 
 
+static gboolean
+gtk_cell_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+                                                     tagname, parser, data);
+}
+
+static void
+gtk_cell_view_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+                                              data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+                                           data);
+}
+
+
 #define __GTK_CELL_VIEW_C__
 #include "gtkaliasdef.c"
index 1f427ca43e9c0334458610a9fc6ec2664e82c99c..d1b7c0060341b3aa097ec607b3eb22e124ec6410 100644 (file)
@@ -24,6 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 #include <config.h>
+#include <string.h>
 #include <glib.h>
 #include "gtkcolorseldialog.h"
 #include "gtkframe.h"
@@ -31,6 +32,7 @@
 #include "gtkbutton.h"
 #include "gtkstock.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 
 /* GtkColorSelectionDialog */
 /***************************/
 
-G_DEFINE_TYPE (GtkColorSelectionDialog, gtk_color_selection_dialog, GTK_TYPE_DIALOG)
+static void gtk_color_selection_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_color_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                                         GtkBuilder   *builder,
+                                                                         const gchar  *childname);
+
+G_DEFINE_TYPE_WITH_CODE (GtkColorSelectionDialog, gtk_color_selection_dialog,
+           GTK_TYPE_DIALOG,
+           G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                      gtk_color_selection_dialog_buildable_interface_init))
+
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
 gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass)
@@ -106,5 +118,30 @@ gtk_color_selection_dialog_new (const gchar *title)
   return GTK_WIDGET (colorseldiag);
 }
 
+static void
+gtk_color_selection_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = gtk_color_selection_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_color_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                        GtkBuilder   *builder,
+                                                        const gchar  *childname)
+{
+    if (strcmp(childname, "ok_button") == 0)
+       return G_OBJECT (GTK_COLOR_SELECTION_DIALOG (buildable)->ok_button);
+    else if (strcmp(childname, "cancel_button") == 0)
+       return G_OBJECT (GTK_COLOR_SELECTION_DIALOG (buildable)->cancel_button);
+    else if (strcmp(childname, "help_button") == 0)
+       return G_OBJECT (GTK_COLOR_SELECTION_DIALOG(buildable)->help_button);
+    else if (strcmp(childname, "color_selection") == 0)
+       return G_OBJECT (GTK_COLOR_SELECTION_DIALOG(buildable)->colorsel);
+
+    return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+
 #define __GTK_COLOR_SELECTION_DIALOG_C__
 #include "gtkaliasdef.c"
index 14dfbe34da4046662f6a00011839ae2a20d38252..742de106e5170eb724682989c7a78d469e299e47 100644 (file)
@@ -438,6 +438,21 @@ static void     gtk_combo_box_child_show                     (GtkWidget       *w
 static void     gtk_combo_box_child_hide                     (GtkWidget       *widget,
                                                              GtkComboBox     *combo_box);
 
+/* GtkBuildable method implementation */
+static GtkBuildableIface *parent_buildable_iface;
+
+static void     gtk_combo_box_buildable_init                 (GtkBuildableIface *iface);
+static gboolean gtk_combo_box_buildable_custom_tag_start     (GtkBuildable  *buildable,
+                                                             GtkBuilder    *builder,
+                                                             GObject       *child,
+                                                             const gchar   *tagname,
+                                                             GMarkupParser *parser,
+                                                             gpointer      *data);
+static void     gtk_combo_box_buildable_custom_tag_end       (GtkBuildable  *buildable,
+                                                             GtkBuilder    *builder,
+                                                             GObject       *child,
+                                                             const gchar   *tagname,
+                                                             gpointer      *data);
 
 /* GtkCellEditable method implementations */
 static void gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
@@ -448,7 +463,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkComboBox, gtk_combo_box, GTK_TYPE_BIN,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
                                                gtk_combo_box_cell_layout_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
-                                               gtk_combo_box_cell_editable_init))
+                                               gtk_combo_box_cell_editable_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_combo_box_buildable_init))
+
 
 /* common */
 static void
@@ -813,6 +831,15 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
   g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate));
 }
 
+static void
+gtk_combo_box_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_combo_box_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_combo_box_buildable_custom_tag_end;
+}
+
 static void
 gtk_combo_box_cell_layout_init (GtkCellLayoutIface *iface)
 {
@@ -5583,5 +5610,36 @@ gtk_combo_box_get_focus_on_click (GtkComboBox *combo_box)
 }
 
 
+static gboolean
+gtk_combo_box_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+                                                     tagname, parser, data);
+}
+
+static void
+gtk_combo_box_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+                                              data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+                                           data);
+}
+
 #define __GTK_COMBO_BOX_C__
 #include "gtkaliasdef.c"
index f8b698a849e6bc93640dc0f570db654c698aba51..eff22d5c4476aa98c91159e338230c0b1d8bbbb1 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcomboboxentry.h"
 #include "gtkcelllayout.h"
 
@@ -26,6 +27,7 @@
 
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GTK_COMBO_BOX_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_COMBO_BOX_ENTRY, GtkComboBoxEntryPrivate))
@@ -60,6 +62,10 @@ static void gtk_combo_box_entry_grab_focus       (GtkWidget *widget);
 static void has_frame_changed                    (GtkComboBoxEntry      *entry_box,
                                                  GParamSpec            *pspec,
                                                  gpointer               data);
+static void gtk_combo_box_entry_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_combo_box_entry_buildable_get_internal_child (GtkBuildable *buildable,
+                                                    GtkBuilder   *builder,
+                                                    const gchar  *childname);
 
 enum
 {
@@ -67,7 +73,9 @@ enum
   PROP_TEXT_COLUMN
 };
 
-G_DEFINE_TYPE (GtkComboBoxEntry, gtk_combo_box_entry, GTK_TYPE_COMBO_BOX)
+G_DEFINE_TYPE_WITH_CODE (GtkComboBoxEntry, gtk_combo_box_entry, GTK_TYPE_COMBO_BOX,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_combo_box_entry_buildable_interface_init))
 
 static void
 gtk_combo_box_entry_class_init (GtkComboBoxEntryClass *klass)
@@ -129,6 +137,23 @@ gtk_combo_box_entry_init (GtkComboBoxEntry *entry_box)
   g_signal_connect (entry_box, "notify::has-frame", G_CALLBACK (has_frame_changed), NULL);
 }
 
+static void
+gtk_combo_box_entry_buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->get_internal_child = gtk_combo_box_entry_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_combo_box_entry_buildable_get_internal_child (GtkBuildable *buildable,
+                                                 GtkBuilder   *builder,
+                                                 const gchar  *childname)
+{
+    if (strcmp (childname, "entry") == 0)
+      return G_OBJECT (gtk_bin_get_child (GTK_BIN (buildable)));
+
+    return NULL;
+}
+
 static void
 gtk_combo_box_entry_set_property (GObject      *object,
                                   guint         prop_id,
index 2040503d95dfbfa816d04a987760a875bcbc0cbc..9305db57d8ac4baea55a8f0a61f88d21b7954a15 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 
 #include "gtkcontainer.h"
+#include "gtkbuildable.h"
 #include "gtkprivate.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
@@ -99,6 +100,24 @@ static void     gtk_container_unmap                (GtkWidget         *widget);
 static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
                                                          GtkWidget    *child);
 
+/* GtkBuildable */
+static void gtk_container_buildable_init           (GtkBuildableIface *iface);
+static void gtk_container_buildable_add            (GtkBuildable *buildable,
+                                                   GtkBuilder   *builder,
+                                                   GObject      *child,
+                                                   const gchar  *type);
+static gboolean gtk_container_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                         GtkBuilder    *builder,
+                                                         GObject       *child,
+                                                         const gchar   *tagname,
+                                                         GMarkupParser *parser,
+                                                         gpointer      *data);
+static void    gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
+                                                      GtkBuilder   *builder,
+                                                      GObject      *child,
+                                                      const gchar  *tagname,
+                                                      gpointer     *data);
+
 
 /* --- variables --- */
 static const gchar           vadjustment_key[] = "gtk-vadjustment";
@@ -110,6 +129,7 @@ static guint                 container_signals[LAST_SIGNAL] = { 0 };
 static GtkWidgetClass       *parent_class = NULL;
 extern GParamSpecPool       *_gtk_widget_child_property_pool;
 extern GObjectNotifyContext *_gtk_widget_child_property_notify_context;
+static GtkBuildableIface    *parent_buildable_iface;
 
 
 /* --- functions --- */
@@ -134,9 +154,21 @@ gtk_container_get_type (void)
        NULL,       /* value_table */
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+       (GInterfaceInitFunc) gtk_container_buildable_init,
+       NULL,
+       NULL
+      };
+
       container_type =
        g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"), 
                                &container_info, G_TYPE_FLAG_ABSTRACT);
+
+      g_type_add_interface_static (container_type,
+                                  GTK_TYPE_BUILDABLE,
+                                  &buildable_info);
+
     }
 
   return container_type;
@@ -260,6 +292,164 @@ gtk_container_class_init (GtkContainerClass *class)
                  GTK_TYPE_WIDGET);
 }
 
+static void
+gtk_container_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_container_buildable_add;
+  iface->custom_tag_start = gtk_container_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_container_buildable_custom_tag_end;
+}
+
+static void
+gtk_container_buildable_add (GtkBuildable  *buildable,
+                            GtkBuilder    *builder,
+                            GObject       *child,
+                            const gchar   *type)
+{
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+}
+
+static void
+gtk_container_buildable_set_child_property (GtkContainer *container,
+                                           GtkWidget    *child,
+                                           gchar        *name,
+                                           const gchar  *value)
+{
+  GParamSpec *pspec;
+  GValue gvalue = { 0, };
+
+  pspec = gtk_container_class_find_child_property
+    (G_OBJECT_GET_CLASS (container), name);
+  if (!pspec)
+    {
+      g_warning ("%s does not have a property called %s",
+                g_type_name (G_OBJECT_TYPE (container)), name);
+      return;
+    }
+
+  if (!gtk_builder_value_from_string (pspec, value, &gvalue))
+    {
+      g_warning ("Could not read property %s:%s with value %s of type %s",
+                g_type_name (G_OBJECT_TYPE (container)),
+                name,
+                value,
+                g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+      return;
+    }
+
+  gtk_container_child_set_property (container, child, name, &gvalue);
+  g_value_unset (&gvalue);
+}
+
+typedef struct {
+  GtkBuilder   *builder;
+  GtkContainer *container;
+  GtkWidget    *child;
+  gchar        *child_prop_name;
+} PackingPropertiesData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer             user_data,
+                         GError             **error)
+{
+  PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "property") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+       parser_data->child_prop_name = g_strdup (values[i]);
+  else if (strcmp (element_name, "packing") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkContainer: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+                        const gchar         *text,
+                        gsize                text_len,
+                        gpointer             user_data,
+                        GError             **error)
+{
+  PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
+
+  if (!parser_data->child_prop_name)
+    return;
+
+  gtk_container_buildable_set_child_property (parser_data->container,
+                                             parser_data->child,
+                                             parser_data->child_prop_name,
+                                             text);
+
+  g_free (parser_data->child_prop_name);
+  parser_data->child_prop_name = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+static gboolean
+gtk_container_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
+{
+  PackingPropertiesData *parser_data;
+
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
+
+  if (child && strcmp (tagname, "packing") == 0)
+    {
+      parser_data = g_slice_new0 (PackingPropertiesData);
+      parser_data->builder = builder;
+      parser_data->container = GTK_CONTAINER (buildable);
+      parser_data->child = GTK_WIDGET (child);
+      parser_data->child_prop_name = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
+{
+  if (strcmp (tagname, "packing") == 0)
+    {
+      g_slice_free (PackingPropertiesData, (gpointer)data);
+      return;
+
+    }
+
+  if (parent_buildable_iface->custom_tag_end)
+    parent_buildable_iface->custom_tag_end (buildable, builder,
+                                           child, tagname, data);
+
+}
+
 /**
  * gtk_container_child_type: 
  * @container: a #GtkContainer
index c70c61768a7d84ecbf0d87633d9ec39b9719240a..5b148c8862ff31ba9767785405ff85075e2b877a 100644 (file)
@@ -42,7 +42,8 @@ typedef enum {
   GTK_DEBUG_MODULES     = 1 << 7,
   GTK_DEBUG_GEOMETRY    = 1 << 8,
   GTK_DEBUG_ICONTHEME   = 1 << 9,
-  GTK_DEBUG_PRINTING   = 1 << 10
+  GTK_DEBUG_PRINTING   = 1 << 10,
+  GTK_DEBUG_BUILDER    = 1 << 11
 } GtkDebugFlag;
 
 #ifdef G_ENABLE_DEBUG
index 93c6ce70f9d02d8cb71423d5ce71a0f2c09ea282..2419689487c9a2976c74b8ad4766b93f11a20963 100644 (file)
@@ -24,6 +24,8 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <stdlib.h>
+#include <string.h>
 #include <config.h>
 #include "gtkbutton.h"
 #include "gtkdialog.h"
@@ -37,6 +39,7 @@
 #include "gtkintl.h"
 #include "gtkbindings.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_DIALOG, GtkDialogPrivate))
@@ -76,6 +79,22 @@ static void gtk_dialog_close             (GtkDialog        *dialog);
 
 static ResponseData* get_response_data   (GtkWidget        *widget,
                                          gboolean          create);
+static void gtk_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                    GtkBuilder   *builder,
+                                                    const gchar  *childname);
+static gboolean gtk_dialog_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                      GtkBuilder    *builder,
+                                                      GObject       *child,
+                                                      const gchar   *tagname,
+                                                      GMarkupParser *parser,
+                                                      gpointer      *data);
+static void gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
+                                                 GtkBuilder   *builder,
+                                                 GObject       *child,
+                                                 const gchar   *tagname,
+                                                 gpointer      user_data);
+
 
 enum {
   PROP_0,
@@ -90,7 +109,9 @@ enum {
 
 static guint dialog_signals[LAST_SIGNAL];
 
-G_DEFINE_TYPE (GtkDialog, gtk_dialog, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE_WITH_CODE (GtkDialog, gtk_dialog, GTK_TYPE_WINDOW,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_dialog_buildable_interface_init))
 
 static void
 gtk_dialog_class_init (GtkDialogClass *class)
@@ -235,6 +256,26 @@ gtk_dialog_init (GtkDialog *dialog)
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
 }
 
+static void
+gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->get_internal_child = gtk_dialog_buildable_get_internal_child;
+  iface->custom_tag_start = gtk_dialog_buildable_custom_tag_start;
+  iface->custom_finished = gtk_dialog_buildable_custom_finished;
+}
+
+static GObject *
+gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                        GtkBuilder   *builder,
+                                        const gchar  *childname)
+{
+    if (strcmp (childname, "vbox") == 0)
+      return G_OBJECT (GTK_DIALOG (buildable)->vbox);
+    else if (strcmp (childname, "action_area") == 0)
+      return G_OBJECT (GTK_DIALOG (buildable)->action_area);
+
+    return NULL;
+}
 
 static void 
 gtk_dialog_set_property (GObject      *object,
@@ -1216,5 +1257,134 @@ gtk_dialog_set_alternative_button_order_from_array (GtkDialog *dialog,
     }
 }
 
+typedef struct {
+  gchar *widget_name;
+  gchar *response_id;
+} ActionWidgetInfo;
+
+typedef struct {
+  GtkDialog *dialog;
+  GtkBuilder *builder;
+  GSList *items;
+  gchar *response;
+} ActionWidgetsSubParserData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer             user_data,
+                         GError             **error)
+{
+  ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "action-widget") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "response") == 0)
+       parser_data->response = g_strdup (values[i]);
+  else if (strcmp (element_name, "action-widgets") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkDialog: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+                        const gchar         *text,
+                        gsize                text_len,
+                        gpointer             user_data,
+                        GError             **error)
+{
+  ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
+  ActionWidgetInfo *item;
+
+  if (!parser_data->response)
+    return;
+
+  item = g_new (ActionWidgetInfo, 1);
+  item->widget_name = g_strndup (text, text_len);
+  item->response_id = parser_data->response;
+  parser_data->items = g_slist_prepend (parser_data->items, item);
+  parser_data->response = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+gboolean
+gtk_dialog_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                      GtkBuilder    *builder,
+                                      GObject       *child,
+                                      const gchar   *tagname,
+                                      GMarkupParser *parser,
+                                      gpointer      *data)
+{
+  ActionWidgetsSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "action-widgets") == 0)
+    {
+      parser_data = g_slice_new0 (ActionWidgetsSubParserData);
+      parser_data->dialog = GTK_DIALOG (buildable);
+      parser_data->items = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
+                                     GtkBuilder   *builder,
+                                     GObject      *child,
+                                     const gchar  *tagname,
+                                     gpointer      user_data)
+{
+  GSList *l;
+  ActionWidgetsSubParserData *parser_data;
+  GObject *object;
+  ResponseData* data;
+
+  if (strcmp (tagname, "action-widgets"))
+    return;
+
+  parser_data = (ActionWidgetsSubParserData*)user_data;
+  parser_data->items = g_slist_reverse (parser_data->items);
+
+  for (l = parser_data->items; l; l = l->next)
+    {
+      ActionWidgetInfo *item = l->data;
+
+      object = gtk_builder_get_object (builder, item->widget_name);
+      if (!object)
+       {
+         g_warning ("Unknown object %s specified in action-widgets %s",
+                    item->widget_name,
+                    gtk_buildable_get_name (GTK_BUILDABLE (object)));
+         continue;
+       }
+
+      data = get_response_data (GTK_WIDGET (object), TRUE);
+      data->response_id = atoi (item->response_id);
+
+      g_free (item->widget_name);
+      g_free (item->response_id);
+      g_free (item);
+    }
+  g_slist_free (parser_data->items);
+  g_slice_free (ActionWidgetsSubParserData, parser_data);
+}
+
 #define __GTK_DIALOG_C__
 #include "gtkaliasdef.c"
index 8df785c158e63fd4ecccf5d020ef5804277372e0..53b87748b9b43c27515805459358216aa64d77e1 100644 (file)
@@ -149,9 +149,15 @@ static void     gtk_entry_completion_insert_completion_text (GtkEntryCompletion
 
 static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
 
+/* GtkBuildable */
+static void     gtk_entry_completion_buildable_init      (GtkBuildableIface  *iface);
+
 G_DEFINE_TYPE_WITH_CODE (GtkEntryCompletion, gtk_entry_completion, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-                                               gtk_entry_completion_cell_layout_init))
+                                               gtk_entry_completion_cell_layout_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_entry_completion_buildable_init))
+
 
 static void
 gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
@@ -386,6 +392,14 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
   g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
 }
 
+static void
+gtk_entry_completion_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
+  iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
+}
+
 static void
 gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface)
 {
index 7d99da960ecd623b025efa8ca913829381dba658..62c08cd3560d950d00b8704e39935813cf6a1f68 100644 (file)
  */
 
 #include <config.h>
-
+#include <string.h>
 #include "gtkexpander.h"
 
 #include "gtklabel.h"
+#include "gtkbuildable.h"
 #include "gtkcontainer.h"
 #include "gtkmarshalers.h"
 #include "gtkmain.h"
@@ -126,7 +127,16 @@ static void gtk_expander_activate (GtkExpander *expander);
 static void get_expander_bounds (GtkExpander  *expander,
                                 GdkRectangle *rect);
 
-G_DEFINE_TYPE (GtkExpander, gtk_expander, GTK_TYPE_BIN)
+/* GtkBuildable */
+static void gtk_expander_buildable_init           (GtkBuildableIface *iface);
+static void gtk_expander_buildable_add            (GtkBuildable *buildable,
+                                                  GtkBuilder   *builder,
+                                                  GObject      *child,
+                                                  const gchar  *type);
+
+G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_expander_buildable_init))
 
 static void
 gtk_expander_class_init (GtkExpanderClass *klass)
@@ -277,6 +287,26 @@ gtk_expander_init (GtkExpander *expander)
   gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
 }
 
+static void
+gtk_expander_buildable_add (GtkBuildable  *buildable,
+                           GtkBuilder    *builder,
+                           GObject       *child,
+                           const gchar   *type)
+{
+  if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else if (strcmp (type, "label") == 0)
+    gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_EXPANDER (buildable), type);
+}
+
+static void
+gtk_expander_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_expander_buildable_add;
+}
+
 static void
 gtk_expander_set_property (GObject      *object,
                           guint         prop_id,
index 095f216ab620e048f206302ad23ff0042b346bab..5be9b7cf0b39a74bb49f05aeb25bfe8cf0342230 100644 (file)
@@ -59,6 +59,7 @@
 #include "gtkintl.h"
 #include "gtkaccessible.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 /* We don't enable the font and style entries because they don't add
@@ -1291,7 +1292,17 @@ gtk_font_selection_set_preview_text  (GtkFontSelection *fontsel,
  * GtkFontSelectionDialog
  *****************************************************************************/
 
-G_DEFINE_TYPE (GtkFontSelectionDialog, gtk_font_selection_dialog, GTK_TYPE_DIALOG);
+static void gtk_font_selection_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                                         GtkBuilder   *builder,
+                                                                         const gchar  *childname);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFontSelectionDialog, gtk_font_selection_dialog,
+                        GTK_TYPE_DIALOG,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_font_selection_dialog_buildable_interface_init))
+
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
@@ -1365,6 +1376,30 @@ gtk_font_selection_dialog_new (const gchar *title)
   return GTK_WIDGET (fontseldiag);
 }
 
+static void
+gtk_font_selection_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = gtk_font_selection_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                       GtkBuilder   *builder,
+                                                       const gchar  *childname)
+{
+    if (strcmp(childname, "ok_button") == 0)
+       return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->ok_button);
+    else if (strcmp(childname, "cancel_button") == 0)
+       return G_OBJECT (GTK_FONT_SELECTION_DIALOG (buildable)->cancel_button);
+    else if (strcmp(childname, "apply_button") == 0)
+       return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->apply_button);
+    else if (strcmp(childname, "font_selection") == 0)
+       return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->fontsel);
+
+    return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
 /**
  * gtk_font_selection_dialog_get_font_name:
  * @fsd: a #GtkFontSelectionDialog
index f5974022fc78e585f891f10e389db16057a2124c..fba55df934b60680f036a94f2df247a74f5e5d66 100644 (file)
@@ -30,6 +30,7 @@
 #include "gtklabel.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define LABEL_PAD 1
@@ -73,7 +74,16 @@ static void gtk_frame_compute_child_allocation      (GtkFrame      *frame,
 static void gtk_frame_real_compute_child_allocation (GtkFrame      *frame,
                                                     GtkAllocation *child_allocation);
 
-G_DEFINE_TYPE (GtkFrame, gtk_frame, GTK_TYPE_BIN)
+/* GtkBuildable */
+static void gtk_frame_buildable_init                (GtkBuildableIface *iface);
+static void gtk_frame_buildable_add                 (GtkBuildable *buildable,
+                                                    GtkBuilder   *builder,
+                                                    GObject      *child,
+                                                    const gchar  *type);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_frame_buildable_init))
 
 static void
 gtk_frame_class_init (GtkFrameClass *class)
@@ -149,6 +159,26 @@ gtk_frame_class_init (GtkFrameClass *class)
   class->compute_child_allocation = gtk_frame_real_compute_child_allocation;
 }
 
+static void
+gtk_frame_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_frame_buildable_add;
+}
+
+static void
+gtk_frame_buildable_add (GtkBuildable *buildable,
+                        GtkBuilder   *builder,
+                        GObject      *child,
+                        const gchar  *type)
+{
+  if (type && strcmp (type, "label") == 0)
+    gtk_frame_set_label_widget (GTK_FRAME (buildable), GTK_WIDGET (child));
+  else if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_FRAME (buildable), type);
+}
+
 static void
 gtk_frame_init (GtkFrame *frame)
 {
index 46db61536395ba133bc3d1acf5ad70171c35eb34..ea7a1933b0a5f3da7158d53adf98cf9328fc7de3 100644 (file)
@@ -450,11 +450,28 @@ static void     clear_source_info                (GtkIconView *icon_view);
 static void     adjust_wrap_width                (GtkIconView     *icon_view,
                                                  GtkIconViewItem *item);
 
+/* GtkBuildable */
+static GtkBuildableIface *parent_buildable_iface;
+static void     gtk_icon_view_buildable_init             (GtkBuildableIface *iface);
+static gboolean gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                         GtkBuilder    *builder,
+                                                         GObject       *child,
+                                                         const gchar   *tagname,
+                                                         GMarkupParser *parser,
+                                                         gpointer      *data);
+static void     gtk_icon_view_buildable_custom_tag_end   (GtkBuildable  *buildable,
+                                                         GtkBuilder    *builder,
+                                                         GObject       *child,
+                                                         const gchar   *tagname,
+                                                         gpointer      *data);
+
 static guint icon_view_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-                                               gtk_icon_view_cell_layout_init))
+                                               gtk_icon_view_cell_layout_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_icon_view_buildable_init))
 
 static void
 gtk_icon_view_class_init (GtkIconViewClass *klass)
@@ -895,6 +912,15 @@ gtk_icon_view_class_init (GtkIconViewClass *klass)
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 }
 
+static void
+gtk_icon_view_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_icon_view_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_icon_view_buildable_custom_tag_end;
+}
+
 static void
 gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
@@ -9236,5 +9262,38 @@ gtk_icon_view_get_accessible (GtkWidget *widget)
   return (* GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->get_accessible) (widget);
 }
 
+static gboolean
+gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+                                                     tagname, parser, data);
+}
+
+static void
+gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+                                              data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+                                           data);
+}
+
+
+
 #define __GTK_ICON_VIEW_C__
 #include "gtkaliasdef.c"
index dc5ebbfa9a1a1de61afb2904a1ad7bd5d0bec3ce..c012afbda393e7ce53b1c5afe0a51028e77f40cf 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 #include <config.h>
+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <gobject/gvaluecollector.h>
 #include "gtktreemodel.h"
@@ -25,6 +27,7 @@
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
@@ -34,6 +37,7 @@ static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_list_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_list_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_list_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -114,6 +118,19 @@ static void     gtk_list_store_set_default_sort_func (GtkTreeSortable        *so
 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
 
 
+/* buildable */
+static gboolean gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                          GtkBuilder    *builder,
+                                                          GObject       *child,
+                                                          const gchar   *tagname,
+                                                          GMarkupParser *parser,
+                                                          gpointer      *data);
+static void     gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
+                                                        GtkBuilder   *builder,
+                                                        GObject      *child,
+                                                        const gchar  *tagname,
+                                                        gpointer     *data);
+
 G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
                                                gtk_list_store_tree_model_init)
@@ -122,7 +139,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
                                                gtk_list_store_drag_dest_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-                                               gtk_list_store_sortable_init))
+                                               gtk_list_store_sortable_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_list_store_buildable_init))
+
 
 static void
 gtk_list_store_class_init (GtkListStoreClass *class)
@@ -176,6 +196,13 @@ gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
 }
 
+void
+gtk_list_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_list_store_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_list_store_buildable_custom_tag_end;
+}
+
 static void
 gtk_list_store_init (GtkListStore *list_store)
 {
@@ -2008,5 +2035,252 @@ gtk_list_store_insert_with_valuesv (GtkListStore *list_store,
   gtk_tree_path_free (path);
 }
 
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GtkBuilder *builder;
+  GObject *object;
+  GSList *column_type_names;
+  GType *column_types;
+  GValue *values;
+  gint *columns;
+  gint last_row;
+  gint n_columns;
+  gint row_column;
+  GQuark error_quark;
+  gboolean is_data;
+} SubParserData;
+
+static void
+list_store_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer             user_data,
+                         GError             **error)
+{
+  guint i;
+  SubParserData *data = (SubParserData*)user_data;
+
+  if (strcmp (element_name, "col") == 0)
+    {
+      int i, id = -1;
+
+      if (data->row_column >= data->n_columns)
+       g_set_error (error, data->error_quark, 0,
+                    "Too many columns, maximum is %d\n", data->n_columns - 1);
+
+      for (i = 0; names[i]; i++)
+       if (strcmp (names[i], "id") == 0)
+         {
+           errno = 0;
+           id = atoi (values[i]);
+           if (errno)
+             g_set_error (error, data->error_quark, 0,
+                          "the id tag %s could not be converted to an integer", values[i]);
+         }
+
+      if (id == -1)
+       g_set_error (error, data->error_quark, 0,
+                    "<col> needs an id attribute");
+
+      data->columns[data->row_column] = id;
+      data->row_column++;
+      data->is_data = TRUE;
+    }
+  else if (strcmp (element_name, "row") == 0)
+    ;
+  else if (strcmp (element_name, "column") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "type") == 0)
+       data->column_type_names = g_slist_prepend (data->column_type_names,
+                                                  g_strdup (values[i]));
+  else if (strcmp (element_name, "columns") == 0)
+    ;
+  else if (strcmp (element_name, "data") == 0)
+    ;
+  else
+    g_set_error (error, data->error_quark, 0,
+                "Unknown start tag: %s", element_name);
+}
+
+static void
+list_store_end_element (GMarkupParseContext *context,
+                       const gchar         *element_name,
+                       gpointer             user_data,
+                       GError             **error)
+{
+  SubParserData *data = (SubParserData*)user_data;
+
+  g_assert (data->builder);
+  
+  if (strcmp (element_name, "row") == 0)
+    {
+      GtkTreeIter iter;
+      int i;
+
+      gtk_list_store_insert_with_valuesv (GTK_LIST_STORE (data->object),
+                                         &iter,
+                                         data->last_row,
+                                         data->columns,
+                                         data->values,
+                                         data->row_column);
+      for (i = 0; i < data->row_column; i++)
+       g_value_unset (&data->values[i]);
+      g_free (data->values);
+      data->values = g_new0 (GValue, data->n_columns);
+      data->last_row++;
+      data->row_column = 0;
+    }
+  else if (strcmp (element_name, "columns") == 0)
+    {
+      GType *column_types;
+      GSList *l;
+      int i;
+      GType type;
+
+      data->column_type_names = g_slist_reverse (data->column_type_names);
+      column_types = g_new0 (GType, g_slist_length (data->column_type_names));
+
+      for (l = data->column_type_names, i = 0; l; l = l->next, i++)
+       {
+         type = gtk_builder_get_type_from_name (data->builder, l->data);
+         if (type == G_TYPE_INVALID)
+           {
+             g_warning ("Unknown type %s specified in treemodel %s",
+                        (const gchar*)l->data,
+                        gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+             continue;
+           }
+         column_types[i] = type;
+
+         g_free (l->data);
+       }
+
+      gtk_list_store_set_column_types (GTK_LIST_STORE (data->object), i,
+                                      column_types);
+
+      g_free (column_types);
+    }
+  else if (strcmp (element_name, "col") == 0)
+    data->is_data = FALSE;
+  else if (strcmp (element_name, "data") == 0)
+    ;
+  else if (strcmp (element_name, "column") == 0)
+    ;
+  else
+    g_set_error (error, data->error_quark, 0,
+                "Unknown end tag: %s", element_name);
+}
+
+static void
+list_store_text (GMarkupParseContext *context,
+                const gchar         *text,
+                gsize                text_len,
+                gpointer             user_data,
+                GError             **error)
+{
+  SubParserData *data = (SubParserData*)user_data;
+  gint i;
+
+  if (!data->is_data)
+    return;
+
+  i = data->row_column - 1;
+
+  if (!gtk_builder_value_from_string_type (data->column_types[i],
+                                          text,
+                                          &data->values[i]))
+    g_error ("Could not convert '%s' to type %s\n",
+            text, g_type_name (data->column_types[i]));
+}
+
+static const GMarkupParser list_store_parser =
+  {
+    list_store_start_element,
+    list_store_end_element,
+    list_store_text
+  };
+
+static gboolean
+gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                          GtkBuilder    *builder,
+                                          GObject       *child,
+                                          const gchar   *tagname,
+                                          GMarkupParser *parser,
+                                          gpointer      *data)
+{
+  SubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "columns") == 0)
+    {
+
+      parser_data = g_slice_new0 (SubParserData);
+      parser_data->builder = builder;
+      parser_data->object = G_OBJECT (buildable);
+      parser_data->column_type_names = NULL;
+
+      *parser = list_store_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  else if (strcmp (tagname, "data") == 0)
+    {
+      gint n_columns = gtk_list_store_get_n_columns (GTK_TREE_MODEL (buildable));
+      if (n_columns == 0)
+       g_error ("Cannot append data to an empty model");
+
+      parser_data = g_slice_new0 (SubParserData);
+      parser_data->builder = builder;
+      parser_data->object = G_OBJECT (buildable);
+      parser_data->values = g_new0 (GValue, n_columns);
+      parser_data->columns = g_new0 (gint, n_columns);
+      parser_data->column_types = GTK_LIST_STORE (buildable)->column_headers;
+      parser_data->n_columns = n_columns;
+      parser_data->last_row = 0;
+      parser_data->error_quark = g_quark_from_static_string ("GtkListStore");
+      
+      *parser = list_store_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  else
+    g_warning ("Unknown custom list store tag: %s", tagname);
+  
+  return FALSE;
+}
+
+static void
+gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
+                                        GtkBuilder   *builder,
+                                        GObject      *child,
+                                        const gchar  *tagname,
+                                        gpointer     *data)
+{
+  SubParserData *sub = (SubParserData*)data;
+  
+  if (strcmp (tagname, "columns") == 0)
+    {
+      g_slist_free (sub->column_type_names);
+      g_slice_free (SubParserData, sub);
+    }
+  else if (strcmp (tagname, "data") == 0)
+    {
+      g_free (sub->columns);
+      g_free (sub->values);
+      g_slice_free (SubParserData, sub);
+    }
+  else
+    g_warning ("Unknown custom list store tag: %s", tagname);
+}
+
 #define __GTK_LIST_STORE_C__
 #include "gtkaliasdef.c"
index d5e9fc20b96be48b0cc09ab8a68db8ab91df79bc..ca9e874bc2f0c886966a7e03bf7268152acbd31f 100644 (file)
@@ -162,7 +162,8 @@ static const GDebugKey gtk_debug_keys[] = {
   {"modules", GTK_DEBUG_MODULES},
   {"geometry", GTK_DEBUG_GEOMETRY},
   {"icontheme", GTK_DEBUG_ICONTHEME},
-  {"printing", GTK_DEBUG_PRINTING}
+  {"printing", GTK_DEBUG_PRINTING},
+  {"builder", GTK_DEBUG_BUILDER}
 };
 #endif /* G_ENABLE_DEBUG */
 
@@ -658,7 +659,7 @@ do_post_parse_initialization (int    *argc,
   }
 
   gtk_type_init (0);
 _gtk_accel_map_init ();  
+ _gtk_accel_map_init ();  
   _gtk_rc_init ();
 
   /* Set the 'initialized' flag.
index 227a4972e7fa1f032609a2156b54edcc4907405e..4297456f1ff5faa36a4ac940f1308a062d7be656 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtknotebook.h"
 #include "gtkmain.h"
 #include "gtkmenu.h"
@@ -38,6 +39,7 @@
 #include "gtkbindings.h"
 #include "gtkprivate.h"
 #include "gtkdnd.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define SCROLL_DELAY_FACTOR   5
@@ -421,6 +423,12 @@ static void do_detach_tab  (GtkNotebook *from,
                            gint         x,
                            gint         y);
 
+/* GtkBuildable */
+static void gtk_notebook_buildable_init           (GtkBuildableIface *iface);
+static void gtk_notebook_buildable_add            (GtkBuildable *buildable,
+                                                  GtkBuilder   *builder,
+                                                  GObject      *child,
+                                                  const gchar  *type);
 
 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
 static gpointer window_creation_hook_data;
@@ -428,7 +436,9 @@ static GDestroyNotify window_creation_hook_destroy = NULL;
 
 static guint notebook_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_notebook_buildable_init))
 
 static void
 add_tab_bindings (GtkBindingSet    *binding_set,
@@ -1095,6 +1105,36 @@ gtk_notebook_init (GtkNotebook *notebook)
   gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
 }
 
+static void
+gtk_notebook_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_notebook_buildable_add;
+}
+
+static void
+gtk_notebook_buildable_add (GtkBuildable  *buildable,
+                           GtkBuilder    *builder,
+                           GObject       *child,
+                           const gchar   *type)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (buildable);
+
+  if (type && strcmp (type, "tab") == 0)
+    {
+      GtkWidget * page;
+
+      page = gtk_notebook_get_nth_page (notebook, -1);
+      /* To set the tab label widget, we must have already a child
+       * inside the tab container. */
+      g_assert (page != NULL);
+      gtk_notebook_set_tab_label (notebook, page, GTK_WIDGET (child));
+    }
+  else if (!type)
+    gtk_notebook_append_page (notebook, GTK_WIDGET (child), NULL);
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (notebook, type);
+}
+
 static gboolean
 gtk_notebook_select_page (GtkNotebook *notebook,
                           gboolean     move_focus)
index af404f0a7c32f7bb87dc69fd7d242a5a7ac03434..477c45f5f157bc558816083c50e47c6ac57fa70f 100644 (file)
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcontainer.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtksizegroup.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 enum {
@@ -49,6 +51,20 @@ static void add_widget_to_closure (GtkWidget         *widget,
                                   GSList           **groups,
                                   GSList           **widgets);
 
+/* GtkBuildable */
+static void gtk_size_group_buildable_init (GtkBuildableIface *iface);
+static gboolean gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                          GtkBuilder    *builder,
+                                                          GObject       *child,
+                                                          const gchar   *tagname,
+                                                          GMarkupParser *parser,
+                                                          gpointer      *data);
+static void gtk_size_group_buildable_custom_finished (GtkBuildable  *buildable,
+                                                     GtkBuilder    *builder,
+                                                     GObject       *child,
+                                                     const gchar   *tagname,
+                                                     gpointer       user_data);
+
 static GQuark size_groups_quark;
 static const gchar size_groups_tag[] = "gtk-size-groups";
 
@@ -310,7 +326,16 @@ gtk_size_group_init (GtkSizeGroup *size_group)
   size_group->ignore_hidden = 0;
 }
 
-G_DEFINE_TYPE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT)
+static void
+gtk_size_group_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_size_group_buildable_custom_tag_start;
+  iface->custom_finished = gtk_size_group_buildable_custom_finished;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_size_group_buildable_init))
 
 static void
 gtk_size_group_set_property (GObject      *object,
@@ -813,5 +838,101 @@ _gtk_size_group_queue_resize (GtkWidget *widget)
   queue_resize_on_widget (widget, TRUE);
 }
 
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+size_group_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer            user_data,
+                         GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  if (strcmp (element_name, "widget") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+       data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+  else if (strcmp (element_name, "widgets") == 0)
+    return;
+  else
+    g_warning ("Unsupported type tag for GtkSizeGroup: %s\n",
+              element_name);
+
+}
+
+static const GMarkupParser size_group_parser =
+  {
+    size_group_start_element
+  };
+
+static gboolean
+gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                          GtkBuilder    *builder,
+                                          GObject       *child,
+                                          const gchar   *tagname,
+                                          GMarkupParser *parser,
+                                          gpointer      *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "widgets") == 0)
+    {
+      parser_data = g_slice_new0 (GSListSubParserData);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+
+      *parser = size_group_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_size_group_buildable_custom_finished (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         gpointer       user_data)
+{
+  GSList *l;
+  GSListSubParserData *data;
+  GObject *object;
+
+  if (strcmp (tagname, "widgets"))
+    return;
+  
+  data = (GSListSubParserData*)user_data;
+  data->items = g_slist_reverse (data->items);
+
+  for (l = data->items; l; l = l->next)
+    {
+      object = gtk_builder_get_object (builder, l->data);
+      if (!object)
+       {
+         g_warning ("Unknown object %s specified in sizegroup %s",
+                    (const gchar*)l->data,
+                    gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+         continue;
+       }
+      gtk_size_group_add_widget (GTK_SIZE_GROUP (data->object),
+                                GTK_WIDGET (object));
+      g_free (l->data);
+    }
+  g_slist_free (data->items);
+  g_slice_free (GSListSubParserData, data);
+}
+
+
 #define __GTK_SIZE_GROUP_C__
 #include "gtkaliasdef.c"
index 4379af70bba0178e63c2f53d536362a9eaa167ed..730c942f5b30c37ce7246ed6e47559c9ed0fbaae 100644 (file)
@@ -24,6 +24,7 @@
 #include "gtktreestore.h"
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -35,6 +36,7 @@ static void         gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
 static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_tree_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_tree_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_tree_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -115,6 +117,21 @@ static void     gtk_tree_store_set_default_sort_func   (GtkTreeSortable        *
                                                        GtkDestroyNotify        destroy);
 static gboolean gtk_tree_store_has_default_sort_func   (GtkTreeSortable        *sortable);
 
+
+/* buildable */
+
+static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                          GtkBuilder    *builder,
+                                                          GObject       *child,
+                                                          const gchar   *tagname,
+                                                          GMarkupParser *parser,
+                                                          gpointer      *data);
+static void     gtk_tree_store_buildable_custom_finished (GtkBuildable          *buildable,
+                                                         GtkBuilder     *builder,
+                                                         GObject        *child,
+                                                         const gchar    *tagname,
+                                                         gpointer        user_data);
+
 static void     validate_gnode                         (GNode *node);
 
 static void     gtk_tree_store_move                    (GtkTreeStore           *tree_store,
@@ -142,7 +159,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, gtk_tree_store, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
                                                gtk_tree_store_drag_dest_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-                                               gtk_tree_store_sortable_init))
+                                               gtk_tree_store_sortable_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_tree_store_buildable_init))
 
 static void
 gtk_tree_store_class_init (GtkTreeStoreClass *class)
@@ -196,6 +215,13 @@ gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
   iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
 }
 
+void
+gtk_tree_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
+  iface->custom_finished = gtk_tree_store_buildable_custom_finished;
+}
+
 static void
 gtk_tree_store_init (GtkTreeStore *tree_store)
 {
@@ -3173,5 +3199,110 @@ validate_gnode (GNode* node)
     }
 }
 
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+tree_model_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **names,
+                         const gchar        **values,
+                         gpointer            user_data,
+                         GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "type") == 0)
+       data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+    }
+}
+
+static const GMarkupParser tree_model_parser =
+  {
+    tree_model_start_element
+  };
+
+
+static gboolean
+gtk_tree_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                          GtkBuilder    *builder,
+                                          GObject       *child,
+                                          const gchar   *tagname,
+                                          GMarkupParser *parser,
+                                          gpointer      *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "columns") == 0)
+    {
+      parser_data = g_slice_new0 (GSListSubParserData);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+
+      *parser = tree_model_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
+                                         GtkBuilder   *builder,
+                                         GObject      *child,
+                                         const gchar  *tagname,
+                                         gpointer      user_data)
+{
+  GSList *l;
+  GSListSubParserData *data;
+  GType *types;
+  int i;
+  GType type;
+
+  if (strcmp (tagname, "columns"))
+    return;
+
+  data = (GSListSubParserData*)user_data;
+  data->items = g_slist_reverse (data->items);
+  types = g_new0 (GType, g_slist_length (data->items));
+
+  for (l = data->items, i = 0; l; l = l->next, i++)
+    {
+      type = gtk_builder_get_type_from_name (builder, l->data);
+      if (type == G_TYPE_INVALID)
+       {
+         g_warning ("Unknown type %s specified in treemodel %s",
+                    (const gchar*)l->data,
+                    gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+         continue;
+       }
+      types[i] = type;
+
+      g_free (l->data);
+    }
+
+  gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
+
+  g_free (types);
+  g_slist_free (data->items);
+  g_slice_free (GSListSubParserData, data);
+}
+
 #define __GTK_TREE_STORE_C__
 #include "gtkaliasdef.c"
index 268389808fb575e13b2c2ec5c27201c0ea658a1d..474c2f038782ee572ddc84e10a08a13a1fd71256 100644 (file)
@@ -29,6 +29,7 @@
 #include "gtkcellrenderer.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
+#include "gtkbuildable.h"
 #include "gtkbutton.h"
 #include "gtkalignment.h"
 #include "gtklabel.h"
@@ -460,6 +461,14 @@ static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree
                                                         GtkTreeViewColumn *column,
                                                         gint               drop_position);
 
+/* GtkBuildable */
+static void gtk_tree_view_buildable_add (GtkBuildable *tree_view,
+                                        GtkBuilder  *builder,
+                                        GObject     *child,
+                                        const gchar *type);
+static void gtk_tree_view_buildable_init (GtkBuildableIface *iface);
+
+
 static gboolean scroll_row_timeout                   (gpointer     data);
 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
 static void     remove_scroll_timeout                (GtkTreeView *tree_view);
@@ -471,7 +480,9 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 /* GType Methods
  */
 
-G_DEFINE_TYPE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_tree_view_buildable_init))
 
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
@@ -1281,6 +1292,12 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   g_type_class_add_private (o_class, sizeof (GtkTreeViewPrivate));
 }
 
+static void
+gtk_tree_view_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_tree_view_buildable_add;
+}
+
 static void
 gtk_tree_view_init (GtkTreeView *tree_view)
 {
@@ -1489,6 +1506,15 @@ gtk_tree_view_finalize (GObject *object)
 
 \f
 
+static void
+gtk_tree_view_buildable_add (GtkBuildable *tree_view,
+                            GtkBuilder  *builder,
+                            GObject     *child,
+                            const gchar *type)
+{
+  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (child));
+}
+
 /* GtkObject Methods
  */
 
index f2d2b9a421a297a7064aaadd0766dcdfafdbbb64..86be0371b7cd9e8b83f44224ec793d193881377c 100644 (file)
@@ -151,12 +151,17 @@ static GList *gtk_tree_view_column_cell_prev                   (GtkTreeViewColum
                                                                GList                  *current);
 static void gtk_tree_view_column_clear_attributes_by_info      (GtkTreeViewColumn      *tree_column,
                                                                GtkTreeViewColumnCellInfo *info);
+/* GtkBuildable implementation */
+static void gtk_tree_view_column_buildable_init                 (GtkBuildableIface     *iface);
 
 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-                                               gtk_tree_view_column_cell_layout_init))
+                                               gtk_tree_view_column_cell_layout_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_tree_view_column_buildable_init))
+
 
 static void
 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
@@ -323,6 +328,14 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
   
 }
 
+static void
+gtk_tree_view_column_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
+  iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
+}
+
 static void
 gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
 {
index 529c296035b509a9ce413239a8d0b2d905af24f4..d1a5ce490686a84b880e0a03ac60c7edec9da31e 100644 (file)
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include <string.h>
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkmenu.h"
@@ -142,6 +143,28 @@ static void        node_prepend_ui_reference      (GNode             *node,
 static void        node_remove_ui_reference       (GNode             *node,
                                                    guint              merge_id);
 
+/* GtkBuildable */
+static void gtk_ui_manager_buildable_init (GtkBuildableIface *iface);
+static void gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *type);
+static GObject* gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+                                                         GtkBuilder   *builder,
+                                                         const gchar  *name);
+static gboolean gtk_ui_manager_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                                          GtkBuilder    *builder,
+                                                          GObject       *child,
+                                                          const gchar   *tagname,
+                                                          GMarkupParser *parser,
+                                                          gpointer      *data);
+static void     gtk_ui_manager_buildable_custom_tag_end (GtkBuildable   *buildable,
+                                                        GtkBuilder      *builder,
+                                                        GObject         *child,
+                                                        const gchar     *tagname,
+                                                        gpointer        *data);
+
+
 
 enum 
 {
@@ -163,7 +186,9 @@ enum
 
 static guint ui_manager_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkUIManager, gtk_ui_manager, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (GtkUIManager, gtk_ui_manager, GTK_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_ui_manager_buildable_init))
 
 static void
 gtk_ui_manager_class_init (GtkUIManagerClass *klass)
@@ -400,6 +425,52 @@ gtk_ui_manager_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_ui_manager_parent_class)->finalize (object);
 }
 
+static void
+gtk_ui_manager_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_ui_manager_buildable_add;
+  iface->construct_child = gtk_ui_manager_buildable_construct_child;
+  iface->custom_tag_start = gtk_ui_manager_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_ui_manager_buildable_custom_tag_end;
+}
+
+static void
+gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+                             GtkBuilder    *builder,
+                             GObject       *child,
+                             const gchar   *type)
+{
+  GtkUIManager *self = GTK_UI_MANAGER (buildable);
+  guint pos;
+
+  g_return_if_fail (GTK_IS_ACTION_GROUP (child));
+
+  pos = g_list_length (self->private_data->action_groups);
+
+  g_object_ref (child);
+  gtk_ui_manager_insert_action_group (self,
+                                     GTK_ACTION_GROUP (child),
+                                     pos);
+}
+
+static GObject *
+gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+                                         GtkBuilder   *builder,
+                                         const gchar  *id)
+{
+  GtkWidget *widget;
+  char *name;
+
+  name = g_strdup_printf ("ui/%s", id);
+  widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name);
+  if (!widget)
+    g_error ("Unknown ui manager child: %s\n", name);
+
+  g_free (name);
+
+  return G_OBJECT (widget);
+}
+
 static void
 gtk_ui_manager_set_property (GObject         *object,
                             guint            prop_id,
@@ -1479,7 +1550,7 @@ add_ui_from_string (GtkUIManager *self,
 
   queue_update (self);
 
-  g_object_notify (G_OBJECT (self), "ui");      
+  g_object_notify (G_OBJECT (self), "ui");
 
   return ctx.merge_id;
 
@@ -2818,6 +2889,49 @@ print_node (GtkUIManager *self,
     g_string_append_printf (buffer, close_fmt, indent_level, "");
 }
 
+static gboolean
+gtk_ui_manager_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                          GtkBuilder    *builder,
+                                          GObject       *child,
+                                          const gchar   *tagname,
+                                          GMarkupParser *parser,
+                                          gpointer      *data)
+{
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "ui") == 0)
+    {
+      ParseContext *ctx;
+
+      ctx = g_new0 (ParseContext, 1);
+      ctx->state = STATE_START;
+      ctx->self = GTK_UI_MANAGER (buildable);
+      ctx->current = NULL;
+      ctx->merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (buildable));
+
+      *data = ctx;
+      *parser = ui_parser;
+
+      return TRUE;
+    }
+
+  return FALSE;
+
+}
+
+static void
+gtk_ui_manager_buildable_custom_tag_end (GtkBuildable *buildable,
+                                        GtkBuilder   *builder,
+                                        GObject      *child,
+                                        const gchar  *tagname,
+                                        gpointer     *data)
+{
+  queue_update (GTK_UI_MANAGER (buildable));
+  g_object_notify (G_OBJECT (buildable), "ui");
+  g_free (data);
+}
+
 /**
  * gtk_ui_manager_get_ui:
  * @self: a #GtkUIManager
index 40917ed5f809363d333b4c22051fb790cf304213..1d47c8c315196838ba5625c877bc5fe664ad034f 100644 (file)
@@ -52,6 +52,7 @@
 #include "gtktooltips.h"
 #include "gtktooltip.h"
 #include "gtkinvisible.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define WIDGET_CLASS(w)         GTK_WIDGET_GET_CLASS (w)
@@ -245,6 +246,28 @@ static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widg
 static void             gtk_widget_set_has_tooltip              (GtkWidget *widget,
                                                                 gboolean   has_tooltip,
                                                                 gboolean   force);
+static void             gtk_widget_buildable_interface_init     (GtkBuildableIface *iface);
+static void             gtk_widget_buildable_set_name           (GtkBuildable     *buildable,
+                                                                 const gchar      *name);
+static const gchar *    gtk_widget_buildable_get_name           (GtkBuildable     *buildable);
+static void             gtk_widget_buildable_set_property       (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 const gchar      *name,
+                                                                 const GValue     *value);
+static gboolean         gtk_widget_buildable_custom_tag_start   (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 GObject          *child,
+                                                                 const gchar      *tagname,
+                                                                 GMarkupParser    *parser,
+                                                                 gpointer         *data);
+static void             gtk_widget_buildable_custom_finshed     (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 GObject          *child,
+                                                                 const gchar      *tagname,
+                                                                 gpointer          data);
+static void             gtk_widget_buildable_parser_finshed     (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder);
+
      
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
                                           gint       width,
@@ -311,11 +334,20 @@ gtk_widget_get_type (void)
        NULL /* interface data */
       };
 
+      const GInterfaceInfo buildable_info =
+      {
+       (GInterfaceInitFunc) gtk_widget_buildable_interface_init,
+       (GInterfaceFinalizeFunc) NULL,
+       NULL /* interface data */
+      };
+
       widget_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
                                            &widget_info, G_TYPE_FLAG_ABSTRACT);
 
       g_type_add_interface_static (widget_type, ATK_TYPE_IMPLEMENTOR,
                                    &accessibility_info) ;
+      g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
+                                   &buildable_info) ;
 
     }
 
@@ -8360,6 +8392,176 @@ gtk_widget_ref_accessible (AtkImplementor *implementor)
   return accessible;
 }
 
+/*
+ * GtkBuildable implementation
+ */
+static GQuark          quark_builder_has_default = 0;
+static GQuark          quark_builder_has_focus = 0;
+
+static void
+gtk_widget_buildable_interface_init (GtkBuildableIface *iface)
+{
+  quark_builder_has_default = g_quark_from_static_string ("gtk-builder-has-default");
+  quark_builder_has_focus = g_quark_from_static_string ("gtk-builder-has-focus");
+
+  iface->set_name = gtk_widget_buildable_set_name;
+  iface->get_name = gtk_widget_buildable_get_name;
+  iface->set_property = gtk_widget_buildable_set_property;
+  iface->parser_finished = gtk_widget_buildable_parser_finshed;
+  iface->custom_tag_start = gtk_widget_buildable_custom_tag_start;
+  iface->custom_finished = gtk_widget_buildable_custom_finshed;
+}
+
+static void
+gtk_widget_buildable_set_name (GtkBuildable *buildable,
+                              const gchar  *name)
+{
+  gtk_widget_set_name (GTK_WIDGET (buildable), name);
+}
+
+static const gchar *
+gtk_widget_buildable_get_name (GtkBuildable *buildable)
+{
+  return gtk_widget_get_name (GTK_WIDGET (buildable));
+}
+
+static void
+gtk_widget_buildable_set_property (GtkBuildable *buildable,
+                                  GtkBuilder   *builder,
+                                  const gchar  *name,
+                                  const GValue *value)
+{
+  if (strcmp (name, "has-default") == 0 && g_value_get_boolean (value))
+      g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_default,
+                         GINT_TO_POINTER (TRUE));
+  else if (strcmp (name, "has-focus") == 0 && g_value_get_boolean (value))
+      g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_focus,
+                         GINT_TO_POINTER (TRUE));
+  else
+    g_object_set_property (G_OBJECT (buildable), name, value);
+}
+
+static void
+gtk_widget_buildable_parser_finshed (GtkBuildable *buildable,
+                                    GtkBuilder   *builder)
+{
+  if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_default))
+    gtk_widget_grab_default (GTK_WIDGET (buildable));
+  if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_focus))
+    gtk_widget_grab_focus (GTK_WIDGET (buildable));
+}
+
+typedef struct {
+  GObject *object;
+  guint    key;
+  guint    modifiers;
+  gchar   *signal;
+} AccelGroupParserData;
+
+static void
+accel_group_start_element (GMarkupParseContext *context,
+                          const gchar         *element_name,
+                          const gchar        **names,
+                          const gchar        **values,
+                          gpointer             user_data,
+                          GError             **error)
+{
+  gint i;
+  guint key = 0;
+  guint modifiers = 0;
+  gchar *signal = NULL;
+  AccelGroupParserData *parser_data = (AccelGroupParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "key") == 0)
+       key = gdk_keyval_from_name (values[i]);
+      else if (strcmp (names[i], "modifiers") == 0)
+       modifiers = _gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, values[i]);
+      else if (strcmp (names[i], "signal") == 0)
+       signal = g_strdup (values[i]);
+    }
+
+  if (key == 0 || signal == NULL)
+    {
+      g_warning ("<accelerator> requires a key or signal attribute");
+      return;
+    }
+  parser_data->key = key;
+  parser_data->modifiers = modifiers;
+  parser_data->signal = signal;
+}
+
+static const GMarkupParser accel_group_parser =
+  {
+    accel_group_start_element,
+  };
+
+static gboolean
+gtk_widget_buildable_custom_tag_start (GtkBuildable     *buildable,
+                                      GtkBuilder       *builder,
+                                      GObject          *child,
+                                      const gchar      *tagname,
+                                      GMarkupParser    *parser,
+                                      gpointer         *data)
+{
+  AccelGroupParserData *parser_data;
+
+  g_assert (buildable);
+
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      parser_data = g_new0 (AccelGroupParserData, 1);
+      parser_data->object = g_object_ref (buildable);
+      *parser = accel_group_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static void
+gtk_widget_buildable_custom_finshed (GtkBuildable *buildable,
+                                    GtkBuilder   *builder,
+                                    GObject      *child,
+                                    const gchar  *tagname,
+                                    gpointer      user_data)
+{
+  AccelGroupParserData *data;
+  GtkWidget *toplevel;
+  GSList *accel_groups;
+  GtkAccelGroup *accel_group;
+
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      data = (AccelGroupParserData*)user_data;
+      g_assert (data->object);
+
+      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (data->object));
+      accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
+      if (g_slist_length (accel_groups) == 0)
+       {
+         accel_group = gtk_accel_group_new ();
+         gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
+       }
+      else
+       {
+         g_assert (g_slist_length (accel_groups) == 1);
+         accel_group = g_slist_nth_data (accel_groups, 0);
+       }
+      gtk_widget_add_accelerator (GTK_WIDGET(data->object),
+                                 data->signal,
+                                 accel_group,
+                                 data->key,
+                                 data->modifiers,
+                                 GTK_ACCEL_VISIBLE);
+      g_object_unref (data->object);
+      g_free (data->signal);
+      g_slice_free (AccelGroupParserData, data);
+    }
+}
+
+
 /**
  * gtk_widget_get_clipboard:
  * @widget: a #GtkWidget
@@ -8652,5 +8854,6 @@ gtk_widget_trigger_tooltip_query (GtkWidget *widget)
   gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (widget));
 }
 
+
 #define __GTK_WIDGET_C__
 #include "gtkaliasdef.c"
index a51c00a7cc76f9e7a671d60ae337b4882f12f1fd..654ed152cba34f213212320c6ae6dbfd2d65208a 100644 (file)
@@ -46,6 +46,7 @@
 #include "gtkicontheme.h"
 #include "gtkmarshalers.h"
 #include "gtkplug.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #ifdef GDK_WINDOWING_X11
@@ -182,6 +183,7 @@ struct _GtkWindowPrivate
 
   guint reset_type_hint : 1;
   guint opacity_set : 1;
+  guint builder_visible : 1;
 
   GdkWindowTypeHint type_hint;
 
@@ -309,6 +311,8 @@ static GQuark       quark_gtk_window_key_hash = 0;
 static GQuark       quark_gtk_window_default_icon_pixmap = 0;
 static GQuark       quark_gtk_window_icon_info = 0;
 
+static GtkBuildableIface *parent_buildable_iface;
+
 static void gtk_window_set_property (GObject         *object,
                                     guint            prop_id,
                                     const GValue    *value,
@@ -318,8 +322,19 @@ static void gtk_window_get_property (GObject         *object,
                                     GValue          *value,
                                     GParamSpec      *pspec);
 
+/* GtkBuildable */
+static void gtk_window_buildable_interface_init  (GtkBuildableIface *iface);
+static void gtk_window_buildable_set_property    (GtkBuildable        *buildable,
+                                                 GtkBuilder          *builder,
+                                                 const gchar         *name,
+                                                 const GValue        *value);
+static void gtk_window_buildable_parser_finished (GtkBuildable     *buildable,
+                                                 GtkBuilder       *builder);
+
 
-G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_window_buildable_interface_init))
 
 static void
 add_tab_bindings (GtkBindingSet    *binding_set,
@@ -1114,6 +1129,39 @@ gtk_window_get_property (GObject      *object,
     }
 }
 
+static void
+gtk_window_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->set_property = gtk_window_buildable_set_property;
+  iface->parser_finished = gtk_window_buildable_parser_finished;
+
+}
+
+static void
+gtk_window_buildable_set_property (GtkBuildable        *buildable,
+                                  GtkBuilder          *builder,
+                                  const gchar         *name,
+                                  const GValue        *value)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
+
+  if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
+    priv->builder_visible = TRUE;
+  else
+    parent_buildable_iface->set_property (buildable, builder, name, value);
+}
+
+static void
+gtk_window_buildable_parser_finished (GtkBuildable *buildable,
+                                     GtkBuilder   *builder)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
+
+  if (priv->builder_visible)
+    gtk_widget_show (GTK_WIDGET (buildable));
+}
+
 /**
  * gtk_window_new:
  * @type: type of window
index 0f2a739ebaa15a85250c69cbede8b755b94eb013..eed40262d819b5541cf98a44a54d74c4c3460c36 100644 (file)
@@ -24,11 +24,12 @@ if USE_X11
 testsocket_programs = testsocket testsocket_child
 endif
 
-TESTS = floatingtest
+TESTS = floatingtest buildertest
 
 noinst_PROGRAMS =                      \
        autotestfilechooser             \
        floatingtest                    \
+       buildertest                     \
        simple                          \
        print-editor                    \
        testaccel                       \
@@ -91,6 +92,7 @@ noinst_PROGRAMS =                     \
 autotestfilechooser_DEPENDENCIES = $(TEST_DEPS)
 simple_DEPENDENCIES = $(TEST_DEPS)
 floatingtest_DEPENDENCIES = $(TEST_DEPS)
+buildertest_DEPENDENCIES = $(TEST_DEPS)
 print_editor_DEPENDENCIES = $(TEST_DEPS)
 testicontheme_DEPENDENCIES = $(TEST_DEPS)
 testiconview_DEPENDENCIES = $(TEST_DEPS)
@@ -146,6 +148,7 @@ testvolumebutton_DEPENDENCIES = $(TEST_DEPS)
 autotestfilechooser_LDADD = $(LDADDS)
 simple_LDADD = $(LDADDS)
 floatingtest_LDADD = $(LDADDS)
+buildertest_LDADD = $(LDADDS)
 print_editor_LDADD = $(LDADDS)
 testaccel_LDADD = $(LDADDS)
 testassistant_LDADD = $(LDADDS)
@@ -205,6 +208,8 @@ testgrouping_LDADD = $(LDADDS)
 testtooltips_LDADD = $(LDADDS)
 testvolumebutton_LDADD = $(LDADDS)
 
+buildertest_LDFLAGS = -export-dynamic
+
 autotestfilechooser_SOURCES =  \
        autotestfilechooser.c
 
diff --git a/tests/buildertest.c b/tests/buildertest.c
new file mode 100644 (file)
index 0000000..b5fbc6b
--- /dev/null
@@ -0,0 +1,1462 @@
+/* buildertest.c
+ * Copyright (C) 2006-2007 Async Open Source
+ * Authors: Johan Dahlin
+ *          Henrique Romano
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkprintjob.h>
+
+static GtkBuilder *
+builder_new_from_string (const gchar *buffer,
+                         gsize length,
+                         gchar *domain)
+{
+  GtkBuilder *builder;
+  builder = gtk_builder_new ();
+  if (domain)
+    gtk_builder_set_translation_domain (builder, domain);
+  gtk_builder_add_from_string (builder, buffer, length, NULL);
+  return builder;
+}
+
+gboolean test_parser (void)
+{
+  GtkBuilder *builder;
+  GError *error;
+  
+  builder = gtk_builder_new ();
+
+  error = NULL;
+  gtk_builder_add_from_string (builder, "<xxx/>", -1, &error);
+  g_assert (error != NULL);
+  g_return_val_if_fail (strcmp (error->message, "Invalid root element: 'xxx'") == 0, FALSE);
+  g_error_free (error);
+  
+  error = NULL;
+  gtk_builder_add_from_string (builder, "<interface invalid=\"X\"/>", -1, &error);
+  g_assert (error != NULL);
+  g_return_val_if_fail (strcmp (error->message, "<input>:1:24 'X' is not a valid attribute of <interface>") == 0, FALSE);
+  g_error_free (error);
+
+  error = NULL;
+  gtk_builder_add_from_string (builder, "<interface><child/></interface>", -1, &error);
+  g_assert (error != NULL);
+  g_return_val_if_fail (strcmp (error->message, "<input>:1:19 'child' is not a valid tag here, expected a 'object' tag") == 0, FALSE);
+  g_error_free (error);
+
+  error = NULL;
+  gtk_builder_add_from_string (builder, "<interface><object class=\"GtkVBox\" id=\"a\"><object class=\"GtkHBox\" id=\"b\"/></object></interface>", -1, &error);
+  g_assert (error != NULL);
+  g_return_val_if_fail (strcmp (error->message, "<input>:1:74 'object' is not a valid tag here") == 0, FALSE);
+  g_error_free (error);
+
+  return TRUE;
+}
+
+  int normal;
+int after;
+int object;
+int object_after;
+
+void
+signal_normal (GtkWindow *window, GParamSpec spec)
+{
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (normal == 0);
+  g_assert (after == 0);
+
+  normal++;
+}
+                    
+void
+signal_after (GtkWindow *window, GParamSpec spec)
+{
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (normal == 1);
+  g_assert (after == 0);
+  
+  after++;
+}
+
+void
+signal_object (GtkButton *button, GParamSpec spec)
+{
+  g_assert (GTK_IS_BUTTON (button));
+  g_assert (object == 0);
+  g_assert (object_after == 0);
+
+  object++;
+}
+
+void
+signal_object_after (GtkButton *button, GParamSpec spec)
+{
+  g_assert (GTK_IS_BUTTON (button));
+  g_assert (object == 1);
+  g_assert (object_after == 0);
+
+  object_after++;
+}
+
+void
+signal_first (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 0);
+  normal = 10;
+}
+
+void
+signal_second (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 10);
+  normal = 20;
+}
+
+void
+signal_extra (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 20);
+  normal = 30;
+}
+
+void
+signal_extra2 (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 30);
+  normal = 40;
+}
+
+gboolean test_connect_signals (void)
+{
+  GtkBuilder *builder;
+  GObject *window;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkButton\" id=\"button\"/>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <signal name=\"notify::title\" handler=\"signal_normal\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_after\" after=\"yes\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_object\""
+    "            object=\"button\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_object_after\""
+    "            object=\"button\" after=\"yes\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_order[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <signal name=\"notify::title\" handler=\"signal_first\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_second\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_extra[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window2\">"
+    "    <signal name=\"notify::title\" handler=\"signal_extra\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_extra2[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window3\">"
+    "    <signal name=\"notify::title\" handler=\"signal_extra2\"/>"
+    "  </object>"
+    "</interface>";
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  gtk_builder_connect_signals (builder, NULL);
+
+  window = gtk_builder_get_object (builder, "window1");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+
+  g_return_val_if_fail (normal == 1, FALSE);
+  g_return_val_if_fail (after == 1, FALSE);
+  g_return_val_if_fail (object == 1, FALSE);
+  g_return_val_if_fail (object_after == 1, FALSE);
+  
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer_order, -1, NULL);
+  gtk_builder_connect_signals (builder, NULL);
+  window = gtk_builder_get_object (builder, "window1");
+  normal = 0;
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 20);
+
+  gtk_builder_add_from_string (builder, buffer_extra,
+                              strlen (buffer_extra), NULL);
+  gtk_builder_add_from_string (builder, buffer_extra2,
+                              strlen (buffer_extra2), NULL);
+  gtk_builder_connect_signals (builder, NULL);
+  window = gtk_builder_get_object (builder, "window2");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 30);
+  window = gtk_builder_get_object (builder, "window3");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 40);
+
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_uimanager_simple (void)
+{
+  GtkBuilder *builder;
+  GObject *uimgr, *menubar;
+  GObject *menu, *label;
+  GList *children;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkUIManager\" id=\"uimgr1\"/>"
+    "</interface>";
+    
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkUIManager\" id=\"uimgr1\">"
+    "    <child>"
+    "      <object class=\"GtkActionGroup\" id=\"ag1\">"
+    "        <child>"
+    "          <object class=\"GtkAction\" id=\"file\">"
+    "            <property name=\"label\">_File</property>"
+    "          </object>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "    <ui>"
+    "      <menubar name=\"menubar1\">"
+    "        <menu action=\"file\">"
+    "        </menu>"
+    "      </menubar>"
+    "    </ui>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkMenuBar\" id=\"menubar1\" constructor=\"uimgr1\"/>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+
+  uimgr = gtk_builder_get_object (builder, "uimgr1");
+  g_return_val_if_fail (uimgr != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_UI_MANAGER (uimgr), FALSE);
+
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+
+  menubar = gtk_builder_get_object (builder, "menubar1");
+  g_return_val_if_fail (menubar != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_MENU_BAR (menubar), FALSE);
+
+  children = gtk_container_get_children (GTK_CONTAINER (menubar));
+  menu = children->data;
+  g_return_val_if_fail (menu != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu), FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (menu)->name, "file") == 0, FALSE);
+  g_list_free (children);
+  
+  label = G_OBJECT (GTK_BIN (menu)->child);
+  g_return_val_if_fail (label != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail
+    (strcmp (gtk_label_get_text (GTK_LABEL (label)), "File") == 0, FALSE);
+  
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_domain (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer1[] = "<interface/>";
+  const gchar buffer2[] = "<interface domain=\"domain\"/>";
+  const gchar *domain;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain == NULL);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer1, -1, "domain-1");
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain-1") == 0);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain") == 0);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, "domain-1");
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain-1") == 0);
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+#if 0
+gboolean test_translation (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label\">"
+    "        <property name=\"label\" translatable=\"yes\">File</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GtkLabel *label;
+
+  setlocale (LC_ALL, "sv_SE");
+  textdomain ("builder");
+  bindtextdomain ("builder", "tests");
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  label = GTK_LABEL (gtk_builder_get_object (builder, "label"));
+  g_assert (strcmp (gtk_label_get_text (label), "Arkiv") == 0);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+#endif
+
+gboolean test_sizegroup (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkVBox\" id=\"vbox1\">"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "    </widgets>"
+    "   </object>"
+    "</interface>";
+  const gchar buffer3[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup2\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkVBox\" id=\"vbox1\">"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *sizegroup;
+  GSList *widgets;
+
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 0, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer3, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup2");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_list_store (void)
+{
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"guint\"/>"
+    "    </columns>"
+    "  </object>"
+    "</interface>";
+  const char buffer2[] = 
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"gint\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">John</col>"
+    "        <col id=\"1\">Doe</col>"
+    "        <col id=\"2\">25</col>"
+    "      </row>"
+    "      <row>"
+    "        <col id=\"0\">Johan</col>"
+    "        <col id=\"1\">Dole</col>"
+    "        <col id=\"2\">50</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "</interface>";
+  GtkBuilder *builder;
+  GObject *store;
+  GtkTreeIter iter;
+  gchar *surname, *lastname;
+  int age;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  store = gtk_builder_get_object (builder, "liststore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT, FALSE);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  store = gtk_builder_get_object (builder, "liststore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 3, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 2) == G_TYPE_INT, FALSE);
+  
+  g_return_val_if_fail (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == TRUE, FALSE);
+  gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                      0, &surname,
+                      1, &lastname,
+                      2, &age,
+                      -1);
+  g_assert (surname != NULL);
+  g_return_val_if_fail (strcmp (surname, "John") == 0, FALSE);
+  g_free (surname);
+  g_assert (lastname != NULL);
+  g_return_val_if_fail (strcmp (lastname, "Doe") == 0, FALSE);
+  g_free (lastname);
+  g_return_val_if_fail (age == 25, FALSE);
+  g_return_val_if_fail (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == TRUE, FALSE);
+  
+  gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                      0, &surname,
+                      1, &lastname,
+                      2, &age,
+                      -1);
+  g_assert (surname != NULL);
+  g_return_val_if_fail (strcmp (surname, "Johan") == 0, FALSE);
+  g_free (surname);
+  g_assert (lastname != NULL);
+  g_return_val_if_fail (strcmp (lastname, "Dole") == 0, FALSE);
+  g_free (lastname);
+  g_return_val_if_fail (age == 50, FALSE);
+  g_return_val_if_fail (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == FALSE, FALSE);
+  
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_tree_store (void)
+{
+  const gchar buffer[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkTreeStore\" id=\"treestore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"guint\"/>"
+    "    </columns>"
+    "  </object>"
+    "</interface>";
+  GtkBuilder *builder;
+  GObject *store;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  store = gtk_builder_get_object (builder, "treestore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT, FALSE);
+  
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_types (void)
+{
+  const gchar buffer[] = 
+    "<interface>"
+    "  <object class=\"GtkAction\" id=\"action\"/>"
+    "  <object class=\"GtkActionGroup\" id=\"actiongroup\"/>"
+    "  <object class=\"GtkAlignment\" id=\"alignment\"/>"
+    "  <object class=\"GtkArrow\" id=\"arrow\"/>"
+    "  <object class=\"GtkButton\" id=\"button\"/>"
+    "  <object class=\"GtkCheckButton\" id=\"checkbutton\"/>"
+    "  <object class=\"GtkDialog\" id=\"dialog\"/>"
+    "  <object class=\"GtkDrawingArea\" id=\"drawingarea\"/>"
+    "  <object class=\"GtkEventBox\" id=\"eventbox\"/>"
+    "  <object class=\"GtkEntry\" id=\"entry\"/>"
+    "  <object class=\"GtkFontButton\" id=\"fontbutton\"/>"
+    "  <object class=\"GtkHButtonBox\" id=\"hbuttonbox\"/>"
+    "  <object class=\"GtkHBox\" id=\"hbox\"/>"
+    "  <object class=\"GtkHPaned\" id=\"hpaned\"/>"
+    "  <object class=\"GtkHRuler\" id=\"hruler\"/>"
+    "  <object class=\"GtkHScale\" id=\"hscale\"/>"
+    "  <object class=\"GtkHScrollbar\" id=\"hscrollbar\"/>"
+    "  <object class=\"GtkHSeparator\" id=\"hseparator\"/>"
+    "  <object class=\"GtkImage\" id=\"image\"/>"
+    "  <object class=\"GtkLabel\" id=\"label\"/>"
+    "  <object class=\"GtkListStore\" id=\"liststore\"/>"
+    "  <object class=\"GtkMenuBar\" id=\"menubar\"/>"
+    "  <object class=\"GtkNotebook\" id=\"notebook\"/>"
+    "  <object class=\"GtkProgressBar\" id=\"progressbar\"/>"
+    "  <object class=\"GtkRadioButton\" id=\"radiobutton\"/>"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup\"/>"
+    "  <object class=\"GtkScrolledWindow\" id=\"scrolledwindow\"/>"
+    "  <object class=\"GtkSpinButton\" id=\"spinbutton\"/>"
+    "  <object class=\"GtkStatusbar\" id=\"statusbar\"/>"
+    "  <object class=\"GtkTextView\" id=\"textview\"/>"
+    "  <object class=\"GtkToggleAction\" id=\"toggleaction\"/>"
+    "  <object class=\"GtkToggleButton\" id=\"togglebutton\"/>"
+    "  <object class=\"GtkToolbar\" id=\"toolbar\"/>"
+    "  <object class=\"GtkTreeStore\" id=\"treestore\"/>"
+    "  <object class=\"GtkTreeView\" id=\"treeview\"/>"
+    "  <object class=\"GtkTable\" id=\"table\"/>"
+    "  <object class=\"GtkVBox\" id=\"vbox\"/>"
+    "  <object class=\"GtkVButtonBox\" id=\"vbuttonbox\"/>"
+    "  <object class=\"GtkVScrollbar\" id=\"vscrollbar\"/>"
+    "  <object class=\"GtkVSeparator\" id=\"vseparator\"/>"
+    "  <object class=\"GtkViewport\" id=\"viewport\"/>"
+    "  <object class=\"GtkVRuler\" id=\"vruler\"/>"
+    "  <object class=\"GtkVPaned\" id=\"vpaned\"/>"
+    "  <object class=\"GtkVScale\" id=\"vscale\"/>"
+    "  <object class=\"GtkWindow\" id=\"window\"/>"
+    "  <object class=\"GtkUIManager\" id=\"uimanager\"/>"
+    "</interface>";
+  GtkBuilder *builder;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_spin_button (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "<object class=\"GtkAdjustment\" id=\"adjustment1\">"
+    "<property name=\"lower\">0</property>"
+    "<property name=\"upper\">10</property>"
+    "<property name=\"step-increment\">2</property>"
+    "<property name=\"page-increment\">3</property>"
+    "<property name=\"page-size\">5</property>"
+    "<property name=\"value\">1</property>"
+    "</object>"
+    "<object class=\"GtkSpinButton\" id=\"spinbutton1\">"
+    "<property name=\"visible\">True</property>"
+    "<property name=\"adjustment\">adjustment1</property>"
+    "</object>"
+    "</interface>";
+  GObject *object;
+  GtkAdjustment *adjustment;
+  gdouble value;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  object = gtk_builder_get_object (builder, "spinbutton1");
+  g_assert (GTK_IS_SPIN_BUTTON (object));
+  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (object));
+  g_assert (GTK_IS_ADJUSTMENT (adjustment));
+  g_object_get (adjustment, "value", &value, NULL);
+  g_return_val_if_fail (value == 1, FALSE);
+  g_object_get (adjustment, "lower", &value, NULL);
+  g_return_val_if_fail (value == 0, FALSE);
+  g_object_get (adjustment, "upper", &value, NULL);
+  g_return_val_if_fail (value == 10, FALSE);
+  g_object_get (adjustment, "step-increment", &value, NULL);
+  g_return_val_if_fail (value == 2, FALSE);
+  g_object_get (adjustment, "page-increment", &value, NULL);
+  g_return_val_if_fail (value == 3, FALSE);
+  g_object_get (adjustment, "page-size", &value, NULL);
+  g_return_val_if_fail (value == 5, FALSE);
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_notebook (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkNotebook\" id=\"notebook1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label1\">"
+    "        <property name=\"label\">label1</property>"
+    "      </object>"
+    "    </child>"
+    "    <child type=\"tab\">"
+    "      <object class=\"GtkLabel\" id=\"tablabel1\">"
+    "        <property name=\"label\">tab_label1</property>"
+    "      </object>"
+    "    </child>"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label2\">"
+    "        <property name=\"label\">label2</property>"
+    "      </object>"
+    "    </child>"
+    "    <child type=\"tab\">"
+    "      <object class=\"GtkLabel\" id=\"tablabel2\">"
+    "        <property name=\"label\">tab_label2</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *notebook;
+  GtkWidget *label;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  notebook = gtk_builder_get_object (builder, "notebook1");
+  g_assert (notebook != NULL);
+  g_return_val_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) == 2,
+                        FALSE);
+
+  label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                                "label1") == 0, FALSE);
+  label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                               "tab_label1") == 0, FALSE);
+
+  label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                                "label2") == 0, FALSE);
+  label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                               "tab_label2") == 0, FALSE);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_construct_only_property (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <property name=\"type\">GTK_WINDOW_POPUP</property>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkTextTagTable\" id=\"tagtable1\"/>"
+    "  <object class=\"GtkTextBuffer\" id=\"textbuffer1\">"
+    "    <property name=\"tag-table\">tagtable1</property>"
+    "  </object>"
+    "</interface>";
+  GObject *widget, *tagtable, *textbuffer;
+  GtkWindowType type;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  widget = gtk_builder_get_object (builder, "window1");
+  g_object_get (widget, "type", &type, NULL);
+  g_return_val_if_fail (type == GTK_WINDOW_POPUP, FALSE);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  textbuffer = gtk_builder_get_object (builder, "textbuffer1");
+  g_return_val_if_fail (textbuffer != NULL, FALSE);
+  g_object_get (textbuffer, "tag-table", &tagtable, NULL);
+  g_return_val_if_fail (tagtable == gtk_builder_get_object (builder, "tagtable1"), FALSE);
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_children (void)
+{
+  GtkBuilder * builder;
+  GList *children;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "        <property name=\"label\">Hello</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkDialog\" id=\"dialog1\">"
+    "    <child internal-child=\"vbox\">"
+    "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
+    "        <property name=\"border-width\">10</property>"
+    "          <child internal-child=\"action_area\">"
+    "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
+    "              <property name=\"border-width\">20</property>"
+    "            </object>"
+    "          </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  GObject *window, *button;
+  GObject *dialog, *vbox, *action_area;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  window = gtk_builder_get_object (builder, "window1");
+  g_return_val_if_fail (window != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  button = gtk_builder_get_object (builder, "button1");
+  g_return_val_if_fail (button != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_WIDGET (button)->parent)->name, "window1") == 0, FALSE);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  dialog = gtk_builder_get_object (builder, "dialog1");
+  g_return_val_if_fail (dialog != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_DIALOG (dialog), FALSE);
+  children = gtk_container_get_children (GTK_CONTAINER (dialog));
+  g_return_val_if_fail (g_list_length (children) == 1, FALSE);
+  g_list_free (children);
+  
+  vbox = gtk_builder_get_object (builder, "dialog1-vbox");
+  g_return_val_if_fail (vbox != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_VBOX (vbox), FALSE);
+  g_return_val_if_fail (GTK_WIDGET (vbox)->parent != NULL, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_WIDGET (vbox)->parent)->name, "dialog1") == 0, FALSE);
+  g_return_val_if_fail (GTK_CONTAINER (vbox)->border_width == 10, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_DIALOG (dialog)->vbox)->name,
+                               "dialog1-vbox") == 0, FALSE);
+
+  action_area = gtk_builder_get_object (builder, "dialog1-action_area");
+  g_return_val_if_fail (action_area != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_HBUTTON_BOX (action_area), FALSE);
+  g_return_val_if_fail (GTK_WIDGET (action_area)->parent != NULL, FALSE);
+  g_return_val_if_fail (GTK_CONTAINER (action_area)->border_width == 20, FALSE);
+  g_return_val_if_fail (GTK_DIALOG (dialog)->action_area != NULL, FALSE);
+  g_return_val_if_fail (GTK_WIDGET (GTK_DIALOG (dialog)->action_area)->name != NULL, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_DIALOG (dialog)->action_area)->name,
+                               "dialog1-action_area") == 0, FALSE);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_child_properties (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkVBox\" id=\"vbox1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label1\"/>"
+    "      <packing>"
+    "        <property name=\"pack-type\">start</property>"
+    "      </packing>"
+    "    </child>"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label2\"/>"
+    "      <packing>"
+    "        <property name=\"pack-type\">end</property>"
+    "      </packing>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  GObject *label, *vbox;
+  GtkPackType pack_type;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  vbox = gtk_builder_get_object (builder, "vbox1");
+  g_return_val_if_fail (GTK_IS_VBOX (vbox), FALSE);
+
+  label = gtk_builder_get_object (builder, "label1");
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  gtk_container_child_get (GTK_CONTAINER (vbox),
+                           GTK_WIDGET (label),
+                           "pack-type",
+                           &pack_type,
+                           NULL);
+  g_return_val_if_fail (pack_type == GTK_PACK_START, FALSE);
+  
+  label = gtk_builder_get_object (builder, "label2");
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  gtk_container_child_get (GTK_CONTAINER (vbox),
+                           GTK_WIDGET (label),
+                           "pack-type",
+                           &pack_type,
+                           NULL);
+  g_return_val_if_fail (pack_type == GTK_PACK_END, FALSE);
+
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_treeview_column (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "<object class=\"GtkListStore\" id=\"liststore1\">"
+    "  <columns>"
+    "    <column type=\"gchararray\"/>"
+    "    <column type=\"guint\"/>"
+    "  </columns>"
+    "  <data>"
+    "    <row>"
+    "      <col id=\"0\">John</col>"
+    "      <col id=\"1\">25</col>"
+    "    </row>"
+    "  </data>"
+    "</object>"
+    "<object class=\"GtkWindow\" id=\"window1\">"
+    "  <child>"
+    "    <object class=\"GtkTreeView\" id=\"treeview1\">"
+    "      <property name=\"visible\">True</property>"
+    "      <property name=\"model\">liststore1</property>"
+    "      <child>"
+    "        <object class=\"GtkTreeViewColumn\" id=\"column1\">"
+    "          <property name=\"title\">Test</property>"
+    "          <child>"
+    "            <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "          </child>"
+    "        </object>"
+    "      </child>"
+    "      <child>"
+    "        <object class=\"GtkTreeViewColumn\" id=\"column2\">"
+    "          <property name=\"title\">Number</property>"
+    "          <child>"
+    "            <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "          </child>"
+    "        </object>"
+    "      </child>"
+    "    </object>"
+    "  </child>"
+    "</object>"
+    "</interface>";
+  GObject *treeview;
+  GtkTreeViewColumn *column;
+  GList *renderers;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  treeview = gtk_builder_get_object (builder, "treeview1");
+  g_return_val_if_fail (treeview, FALSE);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 0);
+  g_return_val_if_fail (strcmp (gtk_tree_view_column_get_title (column),
+                               "Test") == 0, FALSE);
+
+  renderers = gtk_tree_view_column_get_cell_renderers (column);
+  g_return_val_if_fail (g_list_length (renderers) == 1, FALSE);
+  renderer = g_list_nth_data (renderers, 0);
+  g_return_val_if_fail (renderer, FALSE);
+  g_return_val_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer), FALSE);
+  g_list_free (renderers);
+
+  gtk_widget_realize (GTK_WIDGET (treeview));
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "25") == 0, FALSE);
+  g_free (text);
+  
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "John") == 0, FALSE);
+  g_free (text);
+
+  gtk_widget_unrealize (GTK_WIDGET (treeview));
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_icon_view (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"GdkPixbuf\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">test</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkIconView\" id=\"iconview1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"text-column\">0</property>"
+    "        <property name=\"pixbuf-column\">1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "          <attributes>"
+    "            <attribute name=\"text\">0</attribute>"
+    "          </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *iconview;
+  GObject *renderer;
+  gchar *text;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  iconview = gtk_builder_get_object (builder, "iconview1");
+  g_return_val_if_fail (iconview, FALSE);
+  g_return_val_if_fail (GTK_IS_ICON_VIEW (iconview), FALSE);
+
+  gtk_widget_realize (GTK_WIDGET (iconview));
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "test") == 0, FALSE);
+  g_free (text);
+    
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_combo_box (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"guint\"/>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">1</col>"
+    "        <col id=\"1\">Foo</col>"
+    "      </row>"
+    "      <row>"
+    "        <col id=\"0\">2</col>"
+    "        <col id=\"1\">Bar</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkComboBox\" id=\"combobox1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *combobox;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  combobox = gtk_builder_get_object (builder, "combobox1");
+  g_return_val_if_fail (combobox, FALSE);
+  gtk_widget_realize (GTK_WIDGET (combobox));
+
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "Bar") == 0, FALSE);
+  g_free (text);
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "2") == 0, FALSE);
+  g_free (text);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_combo_box_entry (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"guint\"/>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">1</col>"
+    "        <col id=\"1\">Foo</col>"
+    "      </row>"
+    "      <row>"
+    "        <col id=\"0\">2</col>"
+    "        <col id=\"1\">Bar</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkComboBoxEntry\" id=\"comboboxentry1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *combobox;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  combobox = gtk_builder_get_object (builder, "comboboxentry1");
+  g_return_val_if_fail (combobox, FALSE);
+
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "Bar") == 0, FALSE);
+  g_free (text);
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "2") == 0, FALSE);
+  g_free (text);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_cell_view (void)
+{
+  GtkBuilder *builder;
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">test</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkCellView\" id=\"cellview1\">"
+    "   <property name=\"visible\">True</property>"
+    "   <property name=\"model\">liststore1</property>"
+    "   <child>"
+    "     <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "     <attributes>"
+    "       <attribute name=\"text\">0</attribute>"
+    "     </attributes>"
+    "   </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *cellview;
+  GObject *model;
+  GtkTreePath *path;
+  GList *renderers;
+  GObject *renderer;
+  gchar *text;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  g_assert (builder);
+  cellview = gtk_builder_get_object (builder, "cellview1");
+  g_assert (cellview);
+  g_return_val_if_fail (GTK_IS_CELL_VIEW (cellview), FALSE);
+  g_object_get (cellview, "model", &model, NULL);
+  g_assert (model);
+  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+  path = gtk_tree_path_new_first ();
+  gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (cellview), path);
+  
+  renderers = gtk_cell_view_get_cell_renderers (GTK_CELL_VIEW (cellview));
+  g_assert (renderers);
+  g_return_val_if_fail (g_list_length (renderers) == 1, FALSE);
+  
+  gtk_widget_realize (GTK_WIDGET (cellview));
+
+  renderer = g_list_nth_data (renderers, 0);
+  g_list_free (renderers);
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_return_val_if_fail (strcmp (text, "test") == 0, FALSE);
+  g_free (text);
+  gtk_tree_path_free (path);
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_dialog (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkDialog\" id=\"dialog1\">"
+    "    <child internal-child=\"vbox\">"
+    "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
+    "          <child internal-child=\"action_area\">"
+    "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
+    "              <child>"
+    "                <object class=\"GtkButton\" id=\"button_cancel\"/>"
+    "              </child>"
+    "              <child>"
+    "                <object class=\"GtkButton\" id=\"button_ok\"/>"
+    "              </child>"
+    "            </object>"
+    "          </child>"
+    "      </object>"
+    "    </child>"
+    "    <action-widgets>"
+    "      <action-widget response=\"3\">button_ok</action-widget>"
+    "      <action-widget response=\"-5\">button_cancel</action-widget>"
+    "    </action-widgets>"
+    "  </object>"
+    "</interface>";
+
+  GObject *dialog1;
+  GObject *button_ok;
+  GObject *button_cancel;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  dialog1 = gtk_builder_get_object (builder, "dialog1");
+  button_ok = gtk_builder_get_object (builder, "button_ok");
+  g_return_val_if_fail (gtk_dialog_get_response_for_widget
+                        (GTK_DIALOG (dialog1),
+                         GTK_WIDGET (button_ok)) == 3, FALSE);
+  button_cancel = gtk_builder_get_object (builder, "button_cancel");
+  g_return_val_if_fail (gtk_dialog_get_response_for_widget
+                        (GTK_DIALOG (dialog1),
+                         GTK_WIDGET (button_cancel)) == -5, FALSE);
+  
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_accelerators (void)
+{
+  GtkBuilder *builder;
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "        <accelerator key=\"q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"clicked\"/>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  gchar *buffer2 =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkTreeView\" id=\"treeview1\">"
+    "        <signal name=\"cursor-changed\" handler=\"gtk_main_quit\"/>"
+    "        <accelerator key=\"f\" modifiers=\"GDK_CONTROL_MASK\" signal=\"grab_focus\"/>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *window1;
+  GSList *accel_groups;
+  GObject *accel_group;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_return_val_if_fail (g_slist_length (accel_groups) == 1, FALSE);
+  accel_group = g_slist_nth_data (accel_groups, 0);
+  g_assert (accel_group);
+
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_return_val_if_fail (g_slist_length (accel_groups) == 1, FALSE);
+  accel_group = g_slist_nth_data (accel_groups, 0);
+  g_assert (accel_group);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_widget (void)
+{
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "         <property name=\"can-focus\">True</property>"
+    "         <property name=\"has-focus\">True</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+   "</interface>";
+  gchar *buffer2 =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "         <property name=\"can-default\">True</property>"
+    "         <property name=\"has-default\">True</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+   "</interface>";
+  GtkBuilder *builder;
+  GObject *button1;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  button1 = gtk_builder_get_object (builder, "button1");
+
+#if 0
+  g_return_val_if_fail (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (button1)), FALSE);
+#endif
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  button1 = gtk_builder_get_object (builder, "button1");
+
+  g_return_val_if_fail (GTK_WIDGET_RECEIVES_DEFAULT (GTK_WIDGET (button1)), FALSE);
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  
+  g_print ("Testing parser\n");
+  if (!test_parser ())
+    g_error ("test_parser failed");
+
+  g_print ("Testing types\n");
+  if (!test_types ())
+    g_error ("test_types failed");
+
+  g_print ("Testing construct-only property\n");
+  if (!test_construct_only_property ())
+    g_error ("test_construct_only_property failed");
+  
+  g_print ("Testing children\n");
+  if (!test_children ())
+    g_error ("test_children failed");
+
+  g_print ("Testing child properties\n");
+  if (!test_child_properties ())
+    g_error ("test_child_properties failed");
+
+  g_print ("Testing notebook\n");
+  if (!test_notebook ())
+    g_error ("test_notebook failed");
+
+  g_print ("Testing domain\n");
+  if (!test_domain ())
+    g_error ("test_domain failed");
+
+  g_print ("Testing signal autoconnect\n");
+  if (!test_connect_signals ())
+    g_error ("test_connect_signals failed");
+
+  g_print ("Testing uimanager simple\n");
+  if (!test_uimanager_simple ())
+    g_error ("test_uimanager_simple failed");
+
+  g_print ("Testing spin button\n");
+  if (!test_spin_button ())
+    g_error ("test_spin_button failed");
+
+  g_print ("Testing sizegroup\n");
+  if (!test_sizegroup ())
+    g_error ("test_sizegroup failed");
+  
+  g_print ("Testing list store\n");
+  if (!test_list_store ())
+    g_error ("test_list_store failed");
+  
+  g_print ("Testing tree store\n");
+  if (!test_tree_store ())
+    g_error ("test_tree_store failed");
+
+  g_print ("Testing treeview column\n");
+  if (!test_treeview_column ())
+    g_error ("test_treeview_column failed");
+
+  g_print ("Testing iconview\n");
+  if (!test_icon_view ())
+    g_error ("test_icon_view failed");
+
+  g_print ("Testing combobox\n");
+  if (!test_combo_box ())
+    g_error ("test_combo_box failed");
+
+  g_print ("Testing combobox entry\n");
+  if (!test_combo_box_entry ())
+    g_error ("test_combo_box_entry failed");
+
+  g_print ("Testing cell view\n");
+  if (!test_cell_view ())
+    g_error ("test_cell_view failed");
+  
+  g_print ("Testing dialog\n");
+  if (!test_dialog ())
+    g_error ("test_dialog failed");
+
+  g_print ("Testing accelerators\n");
+  if (!test_accelerators ())
+    g_error ("test_accelerators failed");
+
+  g_print ("Testing widget\n");
+  if (!test_widget ())
+    g_error ("test_widget failed");
+
+  return 0;
+}